You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用API时实现Zip文件下载功能的技术咨询

实现方案(默认基于Spring Boot生态)

核心逻辑

API返回zip文件的核心是正确设置HTTP响应头,再将zip文件的字节流写入响应输出流即可触发客户端自动下载,关键响应头配置如下:

  • Content-Type 固定为 application/zip,告知客户端返回的是zip格式文件
  • Content-Disposition 配置为 attachment;filename="xxx.zip",标识该资源为可下载附件,同时指定下载后的默认文件名
  • 可选配置 Content-Length,可让客户端显示准确的下载进度

场景1:已经生成了本地zip文件,直接返回该文件

对应Controller层代码示例:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

@RestController
@RequestMapping("/api")
public class ZipDownloadController {
    // 替换为你实际生成的zip文件存储路径
    private static final String ZIP_FILE_PATH = "/xxx/xxx/generated.zip";

    @GetMapping("/download/zip")
    public void downloadLocalZip(HttpServletResponse response) {
        File zipFile = new File(ZIP_FILE_PATH);
        // 编码文件名,避免中文乱码
        String encodeFileName = URLEncoder.encode(zipFile.getName(), StandardCharsets.UTF_8)
                .replaceAll("\\+", "%20");
        // 设置响应头
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + encodeFileName);
        response.setContentLengthLong(zipFile.length());

        // 读取本地文件写入响应流
        try (
            FileInputStream fis = new FileInputStream(zipFile);
            OutputStream os = response.getOutputStream();
        ) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
            os.flush();
        } catch (IOException e) {
            // 按需添加异常处理逻辑
            e.printStackTrace();
        }
    }
}

场景2:优化方案,zip不落地磁盘直接生成返回

不需要将生成的zip写入本地磁盘,直接把压缩流写入响应,节省磁盘IO开销,代码示例:

@GetMapping("/download/zip")
public void downloadZipOnFly(HttpServletResponse response) {
    // 替换为你要压缩的文件列表
    List<File> files = Arrays.asList(new File("/xxx/file1.txt"), new File("/xxx/file2.jpg"));
    String zipFileName = "导出文件.zip";
    // 编码文件名,避免中文乱码
    String encodeFileName = URLEncoder.encode(zipFileName, StandardCharsets.UTF_8)
            .replaceAll("\\+", "%20");
    // 设置响应头
    response.setContentType("application/zip");
    response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + encodeFileName);

    // 直接将压缩流写入响应
    try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
        for (File file : files) {
            try (FileInputStream fis = new FileInputStream(file)) {
                ZipEntry zipEntry = new ZipEntry(file.getName());
                zipOut.putNextEntry(zipEntry);
                byte[] bytes = new byte[1024];
                int length;
                while((length = fis.read(bytes)) >= 0) {
                    zipOut.write(bytes, 0, length);
                }
                zipOut.closeEntry();
            }
        }
    } catch (IOException e) {
        // 按需添加异常处理逻辑
        e.printStackTrace();
    }
}

前端调用注意事项

如果用Ajax/Axios等方式调用接口,需要指定响应类型为blob,再手动触发下载,示例如下:

axios.get('/api/download/zip', {
  responseType: 'blob' // 必须指定响应类型为二进制blob
}).then(res => {
  // 从响应头解析文件名,也可以自定义
  const fileName = decodeURIComponent(res.headers['content-disposition'].split('filename*=utf-8\'\'')[1])
  const blob = new Blob([res.data], { type: 'application/zip' })
  const downloadUrl = window.URL.createObjectURL(blob)
  const aTag = document.createElement('a')
  aTag.href = downloadUrl
  aTag.download = fileName
  aTag.click()
  window.URL.revokeObjectURL(downloadUrl)
})

注意点

  • 流操作使用try-with-resources语法,自动关闭资源避免泄漏
  • 大文件压缩下载建议添加分块处理逻辑,避免内存溢出
  • 文件名编码使用filename*=utf-8''格式,兼容绝大多数现代浏览器,避免中文乱码

内容的提问来源于stack exchange,提问作者gin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 08:45:07