最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

Java实现打包压缩文件或文件夹生成zip以实现多文件批量下载

来源:博客园


(资料图片)

有时候在系统中需要一次性下载多个文件,但逐个下载文件比较麻烦。这时候,最好的解决办法是将所有文件打包成一个压缩文件,然后下载这个压缩文件,这样就可以一次性获取所有所需的文件了。

下面是一个名为CompressUtil的工具类的代码,它提供了一些方法来处理文件压缩和下载操作:

import org.apache.commons.lang3.ArrayUtils;import org.apache.commons.lang3.StringUtils;import org.apache.lucene.util.RamUsageEstimator;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import java.io.*;import java.util.*;import java.util.zip.*;/** * @author fhey * @date 2023-05-11 20:48:28 * @description: 压缩工具类 */public class CompressUtil {    private static final Logger logger = LoggerFactory.getLogger(CompressUtil.class);    /**     * 将文件打包到zip并创建文件     *     * @param sourceFilePath     * @param zipFilePath     * @throws IOException     */    public static void createLocalCompressFile(String sourceFilePath, String zipFilePath) throws IOException {        createLocalCompressFile(sourceFilePath, zipFilePath, null);    }    /**     * 将文件打包到zip并创建文件     *     * @param sourceFilePath     * @param zipFilePath     * @param zipName     * @throws IOException     */    public static void createLocalCompressFile(String sourceFilePath, String zipFilePath, String zipName) throws IOException {        File sourceFile = new File(sourceFilePath);        if (!sourceFile.exists()) {            throw new RuntimeException(sourceFilePath + "不存在!");        }        if(StringUtils.isBlank(zipName)){            zipName = sourceFile.getName();        }        File zipFile = createNewFile(zipFilePath + File.separator + zipName + ".zip");        try (FileOutputStream fileOutputStream = new FileOutputStream(zipFile)) {            compressFile(sourceFile, fileOutputStream);        }    }    /**     * 获取压缩文件流     *     * @param sourceFilePath     * @return ByteArrayOutputStream     * @throws IOException     */    public static OutputStream compressFile(String sourceFilePath, OutputStream outputStream) throws IOException {        File sourceFile = new File(sourceFilePath);        if (!sourceFile.exists()) {            throw new RuntimeException(sourceFilePath + "不存在!");        }        return compressFile(sourceFile, outputStream);    }    /**     * 获取压缩文件流     *     * @param sourceFile     * @return ByteArrayOutputStream     * @throws IOException     */    private static OutputStream compressFile(File sourceFile, OutputStream outputStream) throws IOException {        try (CheckedOutputStream checkedOutputStream = new CheckedOutputStream(outputStream, new CRC32());             ZipOutputStream zipOutputStream = new ZipOutputStream(checkedOutputStream)) {            doCompressFile(sourceFile, zipOutputStream, StringUtils.EMPTY);            return outputStream;        }    }    /**     * 处理目录下的文件     *     * @param sourceFile     * @param zipOutputStream     * @param zipFilePath     * @throws IOException     */    private static void doCompressFile(File sourceFile, ZipOutputStream zipOutputStream, String zipFilePath) throws IOException {        // 如果文件是隐藏的,不进行压缩        if (sourceFile.isHidden()) {            return;        }        if (sourceFile.isDirectory()) {//如果是文件夹            handDirectory(sourceFile, zipOutputStream, zipFilePath);        } else {//如果是文件就添加到压缩包中            try (FileInputStream fileInputStream = new FileInputStream(sourceFile)) {                //String fileName = zipFilePath + File.separator + sourceFile.getName();                String fileName = zipFilePath + sourceFile.getName();                addCompressFile(fileInputStream, fileName, zipOutputStream);                //String fileName = zipFilePath.replace("\\", "/") + "/" + sourceFile.getName();                //addCompressFile(fileInputStream, fileName, zipOutputStream);            }        }    }    /**     * 处理文件夹     *     * @param dir         文件夹     * @param zipOut      压缩包输出流     * @param zipFilePath 压缩包中的文件夹路径     * @throws IOException     */    private static void handDirectory(File dir, ZipOutputStream zipOut, String zipFilePath) throws IOException {        File[] files = dir.listFiles();        if (ArrayUtils.isEmpty(files)) {            ZipEntry zipEntry = new ZipEntry(zipFilePath + dir.getName() + File.separator);            zipOut.putNextEntry(zipEntry);            zipOut.closeEntry();            return;        }        for (File file : files) {            doCompressFile(file, zipOut, zipFilePath + dir.getName() + File.separator);        }    }    /**     * 获取压缩文件流     *     * @param documentList 需要压缩的文件集合     * @return ByteArrayOutputStream     */    public static OutputStream compressFile(List documentList, OutputStream outputStream) {        Map> documentMap = new HashMap<>();        documentMap.put("", documentList);        return compressFile(documentMap, outputStream);    }    /**     * 将文件打包到zip     *     * @param documentMap 需要下载的附件集合 map的key对应zip里的文件夹名     * @return ByteArrayOutputStream     */    public static OutputStream compressFile(Map> documentMap, OutputStream outputStream) {        CheckedOutputStream checkedOutputStream = new CheckedOutputStream(outputStream, new CRC32());        ZipOutputStream zipOutputStream = new ZipOutputStream(checkedOutputStream);        try {            for (Map.Entry> documentListEntry : documentMap.entrySet()) {                String dirName = documentMap.size() > 1 ? documentListEntry.getKey() : "";                Map fileNameToLen = new HashMap<>();//记录单个合同号文件夹下每个文件名称出现的次数(对重复文件名重命名)                for (FileInfo document : documentListEntry.getValue()) {                    try {                        //防止单个文件夹下文件名重复 对重复的文件进行重命名                        String documentName = document.getFileName();                        if (fileNameToLen.get(documentName) == null) {                            fileNameToLen.put(documentName, 1);                        } else {                            int fileLen = fileNameToLen.get(documentName) + 1;                            fileNameToLen.put(documentName, fileLen);                            documentName = documentName + "(" + fileLen + ")";                        }                        String fileName = documentName + "." + document.getSuffix();                        if (StringUtils.isNotBlank(dirName)) {                            fileName = dirName + File.separator + fileName;                        }                        addCompressFile(document.getFileInputStream(), fileName, zipOutputStream);                    } catch (Exception e) {                        logger.info("filesToZip exception :", e);                    }                }            }        } catch (Exception e) {            logger.error("filesToZip exception:" + e.getMessage(), e);        }        return outputStream;    }    /**     * 将单个文件写入文件压缩包     *     * @param inputStream     文件输入流     * @param fileName        文件在压缩包中的相对全路径     * @param zipOutputStream 压缩包输出流     */    private static void addCompressFile(InputStream inputStream, String fileName, ZipOutputStream zipOutputStream) {        try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {            ZipEntry zipEntry = new ZipEntry(fileName);            zipOutputStream.putNextEntry(zipEntry);            byte[] bytes = new byte[1024];            int length;            while ((length = bufferedInputStream.read(bytes)) >= 0) {                zipOutputStream.write(bytes, 0, length);                zipOutputStream.flush();            }            zipOutputStream.closeEntry();            //System.out.println("map size, value is " + RamUsageEstimator.sizeOf(zipOutputStream));        } catch (Exception e) {            logger.info("addFileToZip exception:", e);            throw new RuntimeException(e);        }    }    /**     * 通过网络请求下载zip     *     * @param sourceFilePath       需要压缩的文件路径     * @param response            HttpServletResponse     * @param zipName            压缩包名称     * @throws IOException     */    public static void httpDownloadCompressFile(String sourceFilePath, HttpServletResponse response, String zipName) throws IOException {        File sourceFile = new File(sourceFilePath);        if (!sourceFile.exists()) {            throw new RuntimeException(sourceFilePath + "不存在!");        }        if(StringUtils.isBlank(zipName)){            zipName = sourceFile.getName();        }        try (ServletOutputStream servletOutputStream = response.getOutputStream()){            CompressUtil.compressFile(sourceFile, servletOutputStream);            response.setContentType("application/zip");            response.setHeader("Content-Disposition", "attachment; filename=\"" + zipName + ".zip\"");            servletOutputStream.flush();        }    }    public static void httpDownloadCompressFileOld(String sourceFilePath, HttpServletResponse response, String zipName) throws IOException {        try (ServletOutputStream servletOutputStream = response.getOutputStream()){            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();            byte[] zipBytes = byteArrayOutputStream.toByteArray();            response.setContentType("application/zip");            response.setHeader("Content-Disposition", "attachment; filename=\"" + zipName + ".zip\"");            response.setContentLength(zipBytes.length);            servletOutputStream.write(zipBytes);            servletOutputStream.flush();        }    }    /**     * 通过网络请求下载zip     *     * @param sourceFilePath       需要压缩的文件路径     * @param response            HttpServletResponse     * @throws IOException     */    public static void httpDownloadCompressFile(String sourceFilePath, HttpServletResponse response) throws IOException {        httpDownloadCompressFile(sourceFilePath, response, null);    }    /**     * 检查文件名是否已经存在,如果存在,就在文件名后面加上“(1)”,如果文件名“(1)”也存在,则改为“(2)”,以此类推。如果文件名不存在,就直接创建一个新文件。     *     * @param filename 文件名     * @return File     */    public static File createNewFile(String filename) {        File file = new File(filename);        if (!file.exists()) {            try {                file.createNewFile();            } catch (IOException e) {                e.printStackTrace();            }        } else {            String base = filename.substring(0, filename.lastIndexOf("."));            String ext = filename.substring(filename.lastIndexOf("."));            int i = 1;            while (true) {                String newFilename = base + "(" + i + ")" + ext;                file = new File(newFilename);                if (!file.exists()) {                    try {                        file.createNewFile();                    } catch (IOException e) {                        e.printStackTrace();                    }                    break;                }                i++;            }        }        return file;    }}

FileInfo类代码:

/** * @author fhey * @date 2023-05-11 21:01:26 * @description: TODO */@Datapublic class FileInfo {    private InputStream fileInputStream;    private String suffix;    private String fileName;        private boolean isDirectory;}

测试压缩并在本地生成文件:

public static void main(String[] args) throws Exception {        //在本地创建压缩文件        CompressUtil.createLocalCompressFile("D:\\书籍\\电子书\\医书", "D:\\test");    }

压缩并在本地生成文件验证结果:

压缩文件并通过http请求下载:

/** * @author fhey */@RestControllerpublic class TestController {    @GetMapping(value = "/testFileToZip")    public void testFileToZip(HttpServletResponse response) throws IOException {        String zipFileName = "myFiles";        String sourceFilePath = "D:\\picture";        CompressUtil.httpDownloadCompressFile(sourceFilePath,response, zipFileName);    }}

压缩文件并通过http请求下载验证结果:

关键词: