批量文件打包下载

最近工作上有个需求,获取批量文件,打包下载,如果源文件名中有重复,则需要重命名(加角标),如果压缩后文件超过20兆,出于宽带考虑,不下载,但给与提示.

思路. 先获取所有文件,重命名,再压缩存起来再判断大小,满足大小写出流,不满足给与提示

 

话不多说,如下代码可以直接运行,赋有运行结果展示.

 

package com.fisher.cloud.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author Fisher
 */
@Controller
@RequestMapping("/test")
public class Test {

    private static final Logger logger = LoggerFactory.getLogger(Test.class);


    @RequestMapping(value = "/download", method = RequestMethod.GET)
    @ResponseBody
    public String downloadAttachment(HttpServletResponse response) throws IOException {
        //测试如下2个目录下的文件打包,两个目录一样的是为了测试重命名问题
        File file1 = new File("D:\\IT\\参考资料\\文件导入导出");
        File file2 = new File("D:\\IT\\参考资料\\文件导入导出");
        File file3 = new File("D:\\IT\\参考资料\\文件下载模板导出方式");

        // 获取所有文件
        List fileList1 = Arrays.asList(file1.listFiles());
        List fileList2 = Arrays.asList(file2.listFiles());
        List fileList3 = Arrays.asList(file3.listFiles());
        List totalFile = new ArrayList<>();
        if (fileList1.size() > 0) {
            for (File f : fileList1) {
                totalFile.add(f);
            }
        }
        if (fileList2.size() > 0) {
            for (File f : fileList2) {
                totalFile.add(f);
            }
        }
        if (fileList3.size() > 0) {
            for (File f : fileList3) {
                totalFile.add(f);
            }
        }
        try {
            // 压缩文件 到"D:\IT\test",名字为 "hello.zip
            File zipFile = this.zipFiles(totalFile, "D:\\IT\\test", "hello.zip");
            // 如果压缩文件大于20兆,返回提示
            Integer maxSize = 20;
            if (maxSize * 1024 * 1024 < zipFile.length()) {
                return "压缩包超过规定的20兆大小,限制下载";
            } else {
                // 将文件写出
                writeOut(response, zipFile);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    // 批量文件压缩成zip包
    public File zipFiles(List fileList, String zipPath, String zipName) throws IOException {
        // 如果被压缩文件中有重复,会重命名
        Map namePathMap = getTransferName(fileList);
        File zipPathFile = new File(zipPath);
        // 文件夹不存在则创建
        if (!zipPathFile.exists()) {
            zipPathFile.mkdirs();
        }
        File zipFile = new File(zipPath + File.separator + zipName);
        if (!zipFile.exists()) {
            zipFile.createNewFile();
        }
        ZipOutputStream zos = null;
        BufferedInputStream bis = null;
        try {
            // 存放的目标文件
            zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile.getPath())));
            Set keySet = namePathMap.keySet();
            ZipEntry zipEntry = null;
            for (String key : keySet) { // key是文件名,value是path
                // 指定源文件
                File sourceFile = new File(namePathMap.get(key));
                // 创建ZIP实体,并添加进压缩包,指定压缩文件中的文件名
                zipEntry = new ZipEntry(key);
                zos.putNextEntry(zipEntry);
                // 读取待压缩的文件并写进压缩包里
                bis = new BufferedInputStream(new BufferedInputStream(new FileInputStream(sourceFile), 1024 * 10));
                byte[] bufs = new byte[1024 * 10];
                int read = 0;
                while ((read = (bis.read(bufs, 0, 1024 * 10))) != -1) {
                    zos.write(bufs, 0, read);
                }
                if (bis != null) {
                    bis.close();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            if (bis != null) {
                bis.close();
            }
            if (null != zos) {
                zos.close();
            }
        }
        return zipFile;

    }

    /**
     * 将文件写出到流 【方法名】{方法的功能/动作描述}
     * @author Fisher
     * 
     * */
    private void writeOut(HttpServletResponse response, File zipFile) throws IOException {
        response.reset();
        response.setContentType("application/zip");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + zipFile.getName());
        OutputStream outputStream = response.getOutputStream();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(zipFile.getPath());
            int len = 0;
            byte[] buffer = new byte[1024];
            while ((len = fis.read(buffer)) > 0) {
                outputStream.write(buffer, 0, len);
            }
            outputStream.flush();
        } finally {
            if (null != fis) {
                fis.close();
            }
            if (null != outputStream) {
                outputStream.close();
            }
        }
    }

    // 计算压缩包如果已存在重复的名称,则在重复文件后面跟上数字 如: 文件(1).doc,文件(2).doc
    public Map getTransferName(List fileList) {
        if (fileList == null || fileList.size() == 0) {
            return new HashMap();
        }
        // key存放文件名,value存放path
        Map fileNameMap = new HashMap<>();
        List fileNames = new ArrayList<>();
        for (File file : fileList) {
            // 获取文件名
            String fileName = file.getName();
            int count = 0;

            for (String name : fileNames) {
                if (name != null && name.equals(fileName)) {
                    count++;
                }
            }
            fileNames.add(fileName);
            if (count > 0) {
                int lastIndex = fileName.lastIndexOf('.');
                String name = fileName.substring(0, lastIndex);
                String type = fileName.substring(lastIndex + 1, fileName.length());
                fileName = new StringBuilder().append(name).append("(").append(count).append(")").append(".")
                        .append(type).toString();
                fileNameMap.put(fileName, file.getPath());
            } else {
                fileNameMap.put(fileName, file.getPath());
            }
        }
        return fileNameMap;
    }

}
 

测试结果:相同名字会重复命名

 

批量文件打包下载_第1张图片

超过20兆不下载,给与提示

批量文件打包下载_第2张图片

 

 

 

 

 

 

 

 

你可能感兴趣的:(批量文件打包下载)