如何在Node.js/TS API中转发Python API的二进制流响应?
Node.js转发二进制ZIP包损坏问题解决
问题背景
- Python API返回包含多份PDF的ZIP包,Content-Type为
application/octet-stream,直接通过浏览器/Postman调用可正常下载解压 - Node.js/TS中间API需要转发该Python API的响应给UI,但下载的ZIP包提示损坏,对比发现响应体字节大小和内容存在差异
原代码
// 调用Python API并转发 const apiResponse = await fetchDoc(Id); res.setHeader('content-type', apiResponse.headers["content-type"]); res.setHeader('content-disposition', apiResponse.headers["content-disposition"]); res.send(apiResponse.result); async fetchDoc(Id) { let response = { error: null, result: null, headers: null }; const result = await request(options); const contentType = result.headers["content-type"]; if (method === 'GET' && contentType !== "application/octet-stream") { logger.info(`GET method result.headers: ${JSON.stringify(result.headers, null, 4)}`); response.result = JSON.parse(result.body) } else { logger.info(`either POST or GET method with octet-stream`); response.result = result.body; } response.headers = result.headers; return response }
问题原因
request库默认会将响应体转换为UTF-8字符串,而二进制ZIP包包含非UTF-8兼容的字节,转换过程中会导致数据损坏,最终转发的ZIP包无法正常解压。
解决方案
1. 修改request配置,保留二进制Buffer
在request的配置中添加encoding: null,让响应体以Buffer形式返回,避免字符串编码转换:
// 修改request的options配置 const options = { // 你的其他请求配置(url、method等) encoding: null // 关键:禁用自动编码,返回原始Buffer };
2. 优化响应转发逻辑
确保转发时直接传递Buffer,同时处理响应头的大小写问题(部分环境下headers键可能为小写):
const apiResponse = await fetchDoc(Id); // 处理响应头的大小写兼容 const contentType = apiResponse.headers['content-type'] || apiResponse.headers['Content-Type']; const contentDisposition = apiResponse.headers['content-disposition'] || apiResponse.headers['Content-Disposition']; res.setHeader('Content-Type', contentType); res.setHeader('Content-Disposition', contentDisposition); // 直接发送Buffer类型的响应体 res.send(apiResponse.result);
3. 完整修改后的fetchDoc函数
async fetchDoc(Id) { let response = { error: null, result: null, headers: null }; // 添加encoding: null到options const options = { // 原有配置 encoding: null }; const result = await request(options); const contentType = result.headers["content-type"]; if (method === 'GET' && contentType !== "application/octet-stream") { logger.info(`GET method result.headers: ${JSON.stringify(result.headers, null, 4)}`); // 手动将Buffer转为UTF-8字符串后解析JSON response.result = JSON.parse(result.body.toString('utf8')); } else { logger.info(`either POST or GET method with octet-stream`); response.result = result.body; // 此时body是Buffer } response.headers = result.headers; return response }
说明
设置encoding: null后,request返回的result.body会是Buffer类型:
- 对于JSON响应,需要手动调用
toString('utf8')转换为字符串后再解析 - 对于二进制响应(如ZIP),直接返回Buffer即可,转发时Express的
res.send会自动处理Buffer的传输
内容的提问来源于stack exchange,提问作者code_grepper
相关产品推荐
相关产品推荐

