Spring Boot中实现多文件打包下载

在Spring Boot中实现多文件打包下载,主要通过将多个文件压缩为ZIP格式并返回给客户端。以下是两种典型实现方案:


​​一、本地文件打包下载​​

​​核心步骤​​

  1. ​接收文件列表参数​
    通过@RequestParam List<String> filenames接收前端传递的文件名列表。
  2. ​动态生成ZIP文件​
    使用ZipOutputStream将文件逐个写入内存流,避免生成物理文件。
  3. ​设置响应头​
    通过Content-Disposition指定文件名,Content-Type设置为application/zip。

​​代码示例​​

scss 复制代码
@GetMapping("/download-multiple")
public ResponseEntity<byte[]> downloadMultipleFiles(@RequestParam List<String> filenames) {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ZipOutputStream zos = new ZipOutputStream(baos)) {
         
        for (String filename : filenames) {
            Path filePath = Paths.get("/path/to/files").resolve(filename).normalize();
            if (Files.exists(filePath)) {
                ZipEntry zipEntry = new ZipEntry(filename);
                zos.putNextEntry(zipEntry);
                Files.copy(filePath, zos);
                zos.closeEntry();
            }
        }
        zos.finish();

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="files.zip"");
        return ResponseEntity.ok().headers(headers).body(baos.toByteArray());
    } catch (IOException e) {
        return ResponseEntity.internalServerError().build();
    }
}

​​关键点​​:

  • 使用try-with-resources自动关闭流,避免资源泄漏。
  • normalize()方法防止路径遍历攻击(如../../)。
  • 内存中生成ZIP,适合小文件场景。

​​二、云存储(MinIO)集成方案​​

若文件存储在云存储(如MinIO),需先获取文件流再压缩:

​​实现步骤​​

  1. ​​配置MinIO客户端​ ​

    添加依赖并配置MinIO连接信息:

    yaml 复制代码
    minio:
      url: http://localhost:9000
      accessKey: your-key
      secretKey: your-secret
      bucketName: your-bucket
  2. ​​动态压缩云存储文件​ ​

    从MinIO获取文件流,直接写入ZIP输出流:

    less 复制代码
    @Autowired
    private MinioClient minioClient;
    
    @GetMapping("/download-zip")
    public void downloadZip(@RequestParam List<String> fileNames, HttpServletResponse response) {
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment; filename=download.zip");
        
        try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
            for (String fileName : fileNames) {
                try (InputStream inputStream = minioClient.getObject(
                        GetObjectArgs.builder().bucket(bucketName).object(fileName).build())) {
                    ZipEntry zipEntry = new ZipEntry(fileName);
                    zos.putNextEntry(zipEntry);
                    IOUtils.copy(inputStream, zos);
                    zos.closeEntry();
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("下载失败", e);
        }
    }

​​优化点​​:

  • 直接流式传输,避免内存溢出。
  • 支持断点续传(需结合HTTP Range请求)。

​​三、注意事项​​

  1. ​内存管理​
    大文件建议使用流式压缩(如ZipOutputStream),避免OutOfMemoryError。
  2. ​路径安全​
    使用normalize()过滤非法路径,防止路径遍历攻击。
  3. ​异常处理​
    捕获IOException并返回明确错误状态码(如404文件不存在)。
  4. ​扩展性​
    可结合分片下载(Range请求)支持大文件断点续传。

​​四、前端调用示例​​

ini 复制代码
// 使用Fetch API触发下载
fetch(`/download-multiple?filenames=file1.txt,file2.jpg`, {
    method: 'GET'
}).then(response => {
    const blob = new Blob([response.blob()]);
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = 'files.zip';
    link.click();
});

通过上述方案,可灵活实现本地或云存储的多文件打包下载,根据实际需求选择内存或流式处理。

相关推荐
SimonKing2 分钟前
又找到一个纯Java的OCR项目,识别的格式还挺多
java·后端·程序员
真上帝的左手39 分钟前
10. 软件设计&架构-架构师之路-1.究竟什么是架构设计?
架构·架构设计
程序猿DD42 分钟前
OctaFuse Gateway 2.17.0:新增维护模式、请求日志汇总、DashScope 语音路由拆分
后端
摸鱼仙人~1 小时前
校招帮简历字段匹配架构分析报告
java·前端·架构
2603_954708311 小时前
微能网协调控制箱的架构优势对能源管理的影响?
大数据·人工智能·分布式·安全·架构
陈随易1 小时前
副业搞钱点子之赛事与活动
前端·后端·程序员
zhongben123_1 小时前
从0到1开发一款生鲜配送APP:核心技术难点与架构避坑指南
大数据·运维·人工智能·ios·架构·web app
Profile排查笔记1 小时前
有哪些开源指纹浏览器项目?先核对客户端、内核与许可证
前端·人工智能·后端·自动化
鶴哥只手遮天2 小时前
雷达系统与成像仿真:从电磁散射到工程实现-第 1 章 雷达系统的分层架构与指标闭环
后端
喵了几个咪2 小时前
GoWind UBA 拆解:把 Doris UNIQUE KEY 翻译成 ClickHouse——读数正确性对齐实录
开发语言·后端·clickhouse·微服务·golang·gowind