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

JSP应用ZIP文件下载功能失效问题求助

解决JSP应用中ZIP文件下载无法触发的问题

你的问题核心在于AJAX请求无法直接触发浏览器的文件下载行为——浏览器不会自动将AJAX返回的二进制流识别为可下载文件,这是AJAX的设计限制。另外你的代码还有几个小细节需要修正,下面一步步来解决:

第一步:修正后端代码的小问题

先把后端的几个错误点改掉,确保返回的文件流是正确的:

  1. 修复ContentType拼写错误:application/octet-stream(你写的octate是笔误)
  2. 把Byte[](包装类数组)转为byte[](原始类型数组),否则response.getOutputStream().write()会报错,因为该方法接受的是原始byte[]
  3. 写完流后记得关闭输出流,避免资源泄漏

修正后的后端代码:

@RequestMapping(value = {"/retrieve"}, method = RequestMethod.POST)
public void logDownload(@RequestBody ResponseDto responseDto, Model model, HttpServletResponse response) throws ServletException, IOException {
    // 把包装类Byte[]转成原始byte[]
    Byte[] arraObj = downloadService.getdownloadFile();
    byte[] byteArray = new byte[arraObj.length];
    for (int i = 0; i < arraObj.length; i++) {
        byteArray[i] = arraObj[i];
    }

    response.setContentType("application/octet-stream");
    response.setHeader("Content-Disposition", "attachment;filename=user.zip");
    // 设置Content-Length,让浏览器知道文件大小
    response.setContentLength(byteArray.length);
    
    OutputStream outputStream = response.getOutputStream();
    outputStream.write(byteArray);
    outputStream.flush();
    outputStream.close();
}

第二步:替换AJAX为合适的下载触发方式

因为AJAX没法直接触发下载,这里给你两种常用方案:

方案1:使用表单提交(最简单直接)

创建一个隐藏的表单,把你的JSON数据作为表单字段提交,模拟POST请求:

// 构建要提交的JSON数据
var retrieveDto = { /* 你的数据内容 */ };
var token = /* 你的CSRF token值 */;

// 创建隐藏表单
var form = document.createElement('form');
form.method = 'POST';
form.action = "${pageContext.request.contextPath}/retrieve";

// 添加CSRF token的隐藏域
var csrfInput = document.createElement('input');
csrfInput.type = 'hidden';
csrfInput.name = 'X-CSRF-TOKEN';
csrfInput.value = token;
form.appendChild(csrfInput);

// 设置表单为JSON格式提交
form.enctype = 'application/json';
var jsonInput = document.createElement('input');
jsonInput.type = 'hidden';
jsonInput.value = JSON.stringify(retrieveDto);
form.appendChild(jsonInput);

// 把表单添加到页面并提交
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);

方案2:用AJAX获取Blob后生成下载链接

如果需要保留AJAX的错误处理等逻辑,可以在AJAX成功后将返回的二进制流转为Blob,然后创建下载链接触发下载:

$.ajax({
    type: 'POST',
    url: "${pageContext.request.contextPath}/retrieve",
    headers: { "X-CSRF-TOKEN": token },
    contentType: "application/json",
    dataType: 'blob', // 这里把dataType改成blob,告诉jQuery返回二进制数据
    data: JSON.stringify(retrieveDto),
    success: function (blob) {
        // 创建下载链接
        var url = window.URL.createObjectURL(blob);
        var a = document.createElement('a');
        a.href = url;
        a.download = 'user.zip'; // 指定下载文件名
        document.body.appendChild(a);
        a.click();
        // 释放临时URL对象
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
        
        // 若需要跳转结果页,可在此添加
        // window.location = "${pageContext.request.contextPath}/result";
    },
    error: function (e) {
        console.log("There was an error with your request..." + JSON.stringify(e));
    }
});

这个方案的关键是把dataType从json改成blob,让jQuery正确解析二进制流,再通过临时链接触发浏览器的下载行为。

为什么原来的AJAX不行?

AJAX的设计目标是在页面后台获取数据并处理,而非触发浏览器的下载弹窗。当浏览器收到AJAX返回的二进制流时,只会把数据交给JavaScript处理,不会自动触发下载,所以需要我们手动创建下载链接来完成这个操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 17:42:35