React接收服务器返回Zip文件无法解压问题求助
问题分析与解决方案
问题根源
- 二进制传输编码丢失:后端用
response.json()返回Zip Buffer时,Node会自动将Buffer序列化为{type: 'Buffer', data: [数字数组]}的JSON结构,原始二进制编码信息在此过程中被破坏。 - 前端Blob创建逻辑错误:直接用
new Blob(data.zipFile.data)创建Blob时,数字数组会被默认按UTF-8编码处理,而Zip是二进制文件,这种转换会彻底破坏文件结构,导致解压失败。 - 截图Zip添加环节的潜在问题:后端中
Buffer.from(content, "utf8")会把page.screenshot()返回的二进制图片数据当成UTF-8字符串解析,可能损坏图片内容(虽本地生成Zip正常,但属于隐患)。
解决方案
方案一:直接返回Zip二进制流(推荐)
跳过JSON序列化,后端直接发送Zip二进制数据并设置正确响应头:
后端Server.js修改:
// 替换原有response.json代码块 const zipToSend = zip.toBuffer(); response.setHeader('Content-Type', 'application/zip'); response.setHeader('Content-Disposition', 'attachment; filename="screenshot-download.zip"'); response.send(zipToSend);
前端App.js修改:
fetch(`/dcsgrab?tearsheetUrl=${screenShotData}&imagefilelocation=${imageFileLocationData}`) .then((response) => response.blob()) .then((zipBlob) => { const url = window.URL.createObjectURL(zipBlob); const zipDownload = document.createElement("a"); zipDownload.href = url; zipDownload.download = "screenshot-download.zip"; document.body.appendChild(zipDownload); zipDownload.click(); window.URL.revokeObjectURL(url); // 释放资源避免内存泄漏 });
方案二:保留JSON传输,前端正确转换二进制数组
若需同时返回提示信息和Zip文件,前端需将数字数组转为Uint8Array后再创建Blob:
前端App.js修改:
fetch(`/dcsgrab?tearsheetUrl=${screenShotData}&imagefilelocation=${imageFileLocationData}`) .then((response) => response.json()) .then((data) => { setMessageData(data.message); setZipData(data.zipFile); // 将数字数组转为Uint8Array,确保二进制数据完整性 const zipBuffer = new Uint8Array(data.zipFile.data); const zipBlob = new Blob([zipBuffer], { type: 'application/zip' }); const url = window.URL.createObjectURL(zipBlob); const zipDownload = document.createElement("a"); zipDownload.href = url; zipDownload.download = "screenshot-download.zip"; document.body.appendChild(zipDownload); zipDownload.click(); window.URL.revokeObjectURL(url); });
必须修正的后端代码
后端添加截图到Zip时,无需对page.screenshot()返回的Buffer做UTF-8转换,直接传入即可:
// 原错误代码 zip.addFile(`screenshot-${screenshotCounter++}.png`, Buffer.from(content, "utf8"), "entry comment goes here"); // 修改后代码 zip.addFile(`screenshot-${screenshotCounter++}.png`, content, "entry comment goes here");
内容的提问来源于stack exchange,提问作者tganyan
相关产品推荐
相关产品推荐

