将多个文件、文件夹压缩成Zip并导出
项目地址:https://gitee.com/libeimaningg/beizhilib
在Spring Boot中将本地多个文件和文件夹压缩成Zip并导出,可以通过以下步骤实现。这里采用流式压缩,避免创建临时文件,适合大文件处理:
一、创建Zip压缩工具类
package org.yaoyao.yaoyaocommon.utils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StreamUtils;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.file.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* Zip工具类
*
* @author Bryson
* @date 2025/4/2
*/
public class ZipUtils {
public static void compressToZip(HttpServletResponse response, String folderPath,
List<String> filePaths,
String zipName) throws IOException {
// 设置响应头
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=\"" + zipName + "\"");
try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
for (String path : filePaths) {
Path filePath = Paths.get(folderPath + "/" + path);
if (Files.exists(filePath)) {
addToZip(filePath, zos, "");
}
}
zos.finish();
} catch (IOException e) {
throw new IOException(e.getMessage());
}
}
private static void addToZip(Path source, ZipOutputStream zos, String parentDir) throws IOException {
String entryName = parentDir + source.getFileName().toString();
if (Files.isDirectory(source)) {
// 处理目录:在Zip中创建目录条目,并递归处理子文件
if (!entryName.endsWith("/")) {
entryName += "/";
}
zos.putNextEntry(new ZipEntry(entryName));
zos.closeEntry();
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(source)) {
for (Path child : dirStream) {
addToZip(child, zos, entryName);
}
}
} else {
// 处理文件:创建条目并写入数据
ZipEntry zipEntry = new ZipEntry(entryName);
zos.putNextEntry(zipEntry);
Files.copy(source, zos);
zos.closeEntry();
}
}
}
二、创建下载请求
1、Controller层
/**
* 将多个文件、文件夹压缩成Zip并导出
* @param response
* @throws IOException
*/
@PostMapping("/downloadZip")
public void downloadZip(HttpServletResponse response) throws IOException {
fileService.downloadZip(response);
}
2、实现层
@Override
public void downloadZip(HttpServletResponse response) throws IOException {
try {
if (FileUtil.exist(folderPath)) {
//获取folderPath路径下的文件名称
List<String> filePaths = FileUtil.listFileNames(folderPath);
//使用时间戳命名压缩包文件
//小记:SimpleDateFormat 是非线程安全的,推荐用 DateTimeFormatte
//如果必须使用 SimpleDateFormat,应通过 ThreadLocal 实现线程隔离
String safeTimestamp = LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
// 调用压缩方法并导出
ZipUtils.compressToZip(response, folderPath, filePaths, safeTimestamp + ".zip");
} else {
throw new BusinessException(StatusEnums.FAIL, BusinessEnums.FAIL.getType(), "文件不存在");
}
} catch (Exception e) {
log.info("###############zip文件生成失败###############");
e.printStackTrace();
}
}
folderPath="E:\file"

List<\String> filePaths的数据为这些文件的名称。
三、导出结果

四、关键点说明
1. 流式压缩
- 直接使用HttpServletResponse的输出流,避免内存溢出
- 使用try-with-resources确保资源自动关闭
2. 目录处理
- 自动识别目录并递归处理子文件
- 在Zip中创建目录条目(以/结尾)
3. 编码处理
- 默认使用UTF-8编码文件名
- 如需处理特殊字符,可添加:
response.setCharacterEncoding("UTF-8");
4. 大文件支持
- 使用NIO的Files.copy()方法实现高效文件复制
- 每次只处理一个文件,内存占用恒定

浙公网安备 33010602011771号