Node服务如何在单个HTTP响应中返回多个Buffer类型的图片数据?
解决方案
问题根源
- 服务端直接将Buffer对象传入JSON序列化,二进制数据不能直接在JSON中传输,需要先编码为可序列化的字符串格式
- 客户端fetch返回的
response.body是原始可读流,需要先调用内置方法消费流才能拿到实际返回内容
服务端代码修改
首先修正两处问题:
- 从arrayBuffer创建Buffer不需要指定
base64编码参数,该参数仅用于从base64格式的字符串转Buffer时使用 - 将Buffer转成base64字符串后再放入返回体,确保JSON序列化正常
const response1 = await fetch(imageUrls[0]); const response2 = await fetch(imageUrls[1]); const arrayBuffer1 = await response1.arrayBuffer(); const arrayBuffer2 = await response2.arrayBuffer(); // 修正Buffer创建方式,转base64字符串 const buffer1 = Buffer.from(arrayBuffer1); const buffer2 = Buffer.from(arrayBuffer2); const base64_1 = buffer1.toString('base64'); const base64_2 = buffer2.toString('base64'); // 同时记录原始文件类型,方便客户端转Blob时使用 const type1 = response1.headers.get('content-type'); const type2 = response2.headers.get('content-type'); res.setHeader("Content-Type", "application/json"); res.send( JSON.stringify({ first: { data: base64_1, type: type1 }, second: { data: base64_2, type: type2 } }) );
客户端代码修改
- 调用
response.json()方法消费流,直接获得解析完成的JSON对象 - 将base64字符串转回Blob后触发下载
fetch(endpoint + '?' + new URLSearchParams(paramsObj), { method: "GET", headers: { "Content-type": "application/json", }, }) .then(async (response) => { // 直接调用json()方法获取解析后的返回数据 const { first, second } = await response.json(); // base64转Blob工具方法 const base64ToBlob = (base64, type = 'application/octet-stream') => { const byteCharacters = atob(base64); const byteNumbers = new Array(byteCharacters.length); for (let i = 0; i < byteCharacters.length; i++) { byteNumbers[i] = byteCharacters.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); return new Blob([byteArray], { type }); }; // 分别转Blob后下载 const blob1 = base64ToBlob(first.data, first.type); download(blob1); const blob2 = base64ToBlob(second.data, second.type); download(blob2); })
可选优化方案(避免base64体积损耗)
如果对传输体积敏感,可以不使用JSON格式,改用multipart/form-data格式返回二进制内容,无需base64编码,可减少33%左右的传输体积:服务端返回时设置Content-Type: multipart/form-data; boundary=自定义分隔符,按格式拼接两个Buffer内容即可,客户端可以用response.formData()直接读取两个文件对象。
内容的提问来源于stack exchange,提问作者zanmato
相关产品推荐
相关产品推荐

