React中如何正确解压gzip压缩的AWS API Gateway Lambda响应
问题根因与修复方案
你的代码输出乱码核心是3个错误:
- 解压逻辑写反了:你定义的
ungzip函数里调用的是zlib.gzip(),这个方法是用来压缩数据的,把已经压缩好的gzip二进制再执行一次压缩操作,输出必然是乱码,gzip解压对应的API是zlib.gunzip() - 运行环境不匹配:React运行在浏览器端,原生不存在Node.js的
Buffer、zlib模块,就算你打了polyfill,也没必要额外引入依赖,浏览器原生API就能完成全流程 - 多余的转码操作:zlib解压完成后返回的本身就是可直接转字符串的二进制数据,你额外套一层
Buffer.from(ungzipedData, 'utf8')属于重复转码,会破坏原始字节数据。
推荐实现(零依赖,浏览器原生支持)
不需要引入任何Node.js相关polyfill,直接用浏览器内置的压缩解压API即可,兼容性覆盖所有主流现代浏览器:
// 接口返回的json数据 const baseData = await response.json(); /** * 解压base64编码的gzip日志内容 * @param {string} base64Gzip 后端返回的base64格式gzip压缩串 * @returns {Promise<string>} 可读的utf8日志文本 */ async function parseGzipLog(base64Gzip) { // 第一步:base64转二进制字节数组 const binaryStr = atob(base64Gzip); const bytes = new Uint8Array(binaryStr.length); for (let i = 0; i < binaryStr.length; i++) { bytes[i] = binaryStr.charCodeAt(i); } // 第二步:原生gzip解压 const ds = new DecompressionStream('gzip'); const decompressedStream = new Blob([bytes]).stream().pipeThrough(ds); // 第三步:解压后的流转utf8文本 return new Response(decompressedStream).text(); } // 调用即可拿到正常日志 const readableLog = await parseGzipLog(baseData.data); console.log(readableLog);
已配置Node.js polyfill的修复写法
如果你的项目已经给zlib、buffer打了浏览器端polyfill,只需要修正原代码的错误即可:
import zlib from 'zlib'; import { Buffer } from 'buffer'; const baseData = await response.json(); // 修正:调用gunzip做解压,不要用gzip const ungzip = (input) => { return new Promise((resolve, reject) => { zlib.gunzip(input, (err, decompressedData) => { if (err) return reject(err); resolve(decompressedData); }); }); }; const gzipBuffer = Buffer.from(baseData.data, 'base64'); const decompressedBuffer = await ungzip(gzipBuffer); // 直接调用toString转utf8,去掉多余的Buffer.from包裹 console.log(decompressedBuffer.toString('utf8'));
注意:如果你的后端返回的gzip数据带自定义头、或者压缩时用了特殊编码,需要确认后端压缩时的参数和前端解压参数一致,否则也可能出现乱码,常规默认参数的gzip压缩用上面的代码都能正常解析。
内容的提问来源于stack exchange,提问作者BRICKLEBERRYoverflow
相关产品推荐
相关产品推荐

