AJAX下载生成的Zip文件无法打开问题排查求助
问题分析与解决
你的问题核心是AJAX默认以文本格式处理响应,导致后端返回的Zip二进制数据被错误解析成字符串,字节流损坏,所以下载后的文件无法打开。下面是具体的修复步骤:
前端修改(关键)
需要告诉AJAX请求接收二进制数据,而非默认的文本格式。修改jQuery AJAX代码,添加xhrFields指定响应类型为blob,同时调整回调里的Blob创建逻辑:
$("#btnFileDown").click(function() { var obj = $("#grid") var ids = obj.getGridParam("selarrrow"); var params = new Array(); for(var i = 0; i < ids.length; i++) { var data = obj.getRowData(ids[i]); params.push(data); } $.ajax({ type: 'POST', url : baseUrl + "fileDownload.et", data : {data:JSON.stringify(params)}, // 指定接收二进制Blob数据 xhrFields: { responseType: 'blob' }, success: function(data, textStatus, xhr) { let disposition = xhr.getResponseHeader('Content-Disposition'); let filename; if (disposition && disposition.indexOf('attachment') !== -1) { let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; let matches = filenameRegex.exec(disposition); if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, ''); } // 直接使用返回的Blob数据,无需二次包装 let link = document.createElement('a'); link.href = window.URL.createObjectURL(data); link.download = filename; link.click(); // 释放URL对象,避免内存泄漏 window.URL.revokeObjectURL(link.href); }, error: function(jqXHR, textStatus, errorThrown) { alert("Failed => " + errorThrown); } }); });
后端补充优化
后端已能生成正确Zip文件,可补充两个细节避免潜在问题:
- 自动关闭输入输出流,释放资源
- 设置
Content-Length头,让浏览器准确识别文件大小
修改后的后端代码:
@RequestMapping("fileDownload.et") @Transactional public void fileDownload(@RequestParam Map<String, Object> param, ModelMap modelMap, HttpServletResponse response) throws ParseException, FileNotFoundException, IOException { // After creating ZipFile Code. response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(zipFile.getName(), "UTF-8")); response.setHeader("Content-Transfer-Encoding", "binary"); // 设置文件长度 response.setContentLengthLong(zipFile.length()); // try-with-resources 自动关闭流 try (FileInputStream fin = new FileInputStream(zipFile); ServletOutputStream fout = response.getOutputStream()) { byte b[] = new byte[4096]; // 4KB缓冲区更高效,避免一次性读取大文件 int leng = 0; while ((leng = fin.read(b)) > 0) { fout.write(b, 0, leng); } fout.flush(); // 确保所有数据写入响应 } }
原代码失效原因
之前的AJAX未指定responseType,jQuery会把后端返回的二进制数据当成UTF-8文本解析,破坏了Zip文件的字节结构(部分字节被转成乱码字符),最终生成的Blob自然损坏,无法正常打开。
内容的提问来源于stack exchange,提问作者King Henry
相关产品推荐
相关产品推荐

