JSP应用ZIP文件下载功能失效问题求助
解决JSP应用中ZIP文件下载无法触发的问题
你的问题核心在于AJAX请求无法直接触发浏览器的文件下载行为——浏览器不会自动将AJAX返回的二进制流识别为可下载文件,这是AJAX的设计限制。另外你的代码还有几个小细节需要修正,下面一步步来解决:
第一步:修正后端代码的小问题
先把后端的几个错误点改掉,确保返回的文件流是正确的:
- 修复ContentType拼写错误:
application/octet-stream(你写的octate是笔误) - 把
Byte[](包装类数组)转为byte[](原始类型数组),否则response.getOutputStream().write()会报错,因为该方法接受的是原始byte[] - 写完流后记得关闭输出流,避免资源泄漏
修正后的后端代码:
@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
相关产品推荐
相关产品推荐

