因CompressionStream兼容性差且不支持同步操作,pako作为纯JS zlib实现,兼容性好、API稳定,支持deflate/gzip双格式,但需注意区分raw deflate与gzip header。

为什么用 pako 而不是原生 CompressionStream
因为 CompressionStream 在 Safari 和部分旧版 Chrome 中不支持,且无法处理同步压缩/解压(比如在 Web Worker 或 Node.js 服务端预处理时)。pako 是 zlib 的纯 JS 实现,兼容性好、API 稳定,适合需要可靠跨环境压缩的场景。
它默认使用 deflate 算法(和 gzip 底层一致),但不自带 gzip header —— 所以压缩结果不是标准 .gz 文件,除非你手动加 header。
pako.deflate 和 pako.inflate 怎么用
这是最常用的两个函数:一个压缩,一个解压,都只接受 Uint8Array 输入。字符串需先转成 UTF-8 字节数组,不能直接传 string。
- 用
new TextEncoder().encode(str)将字符串转为字节数组 - 压缩后得到的仍是
Uint8Array,如需 base64 可用btoa(String.fromCharCode(...arr)) - 解压前必须确保输入是有效的 deflate 流 —— 如果是从后端收到的 gzip 数据,得先去掉 header 和 footer,或改用
pako.ungzip
const pako = require('pako'); // Node.js
// 或通过 CDN 加载:
const str = 'hello world'.repeat(100);
const input = new TextEncoder().encode(str);
const compressed = pako.deflate(input); // Uint8Array
const restored = pako.inflate(compressed);
const decoded = new TextDecoder().decode(restored);
console.log(decoded === str); // true
如何压缩成标准 gzip 格式(含 header)
pako.gzip 和 pako.ungzip 才生成/识别带 RFC 1952 header 的数据,也就是浏览器 fetch 响应里常见的 Content-Encoding: gzip 格式。
立即学习“Java免费学习笔记(深入)”;
-
pako.deflate输出的是 raw deflate;pako.gzip输出才是 gzip - Node.js 里如果要写入
.gz文件,必须用pako.gzip,否则 gunzip 会报unknown compression format - 注意:gzip 比 deflate 多 18 字节 header/footer,体积略大,但通用性更强
const compressedGz = pako.gzip(input);
// 写入文件或发送到服务端时可直接用
fs.writeFileSync('data.txt.gz', compressedGz);
常见错误:解压失败报 invalid stored block lengths
这基本等于“你拿 deflate 数据去调了 pako.ungzip”,或者反过来:用 pako.inflate 解 gzip 数据。
- 检查原始数据来源:如果是
fetch响应且response.headers.get('content-encoding') === 'gzip',就该用pako.ungzip - 如果后端返回的是 raw deflate(比如某些 WebSocket 协议自定义压缩),才用
pako.inflate - 用
console.log(data.slice(0, 4))看前 4 字节:gzip 开头是[0x1f, 0x8b],deflate raw 通常以[0x78]或[0x1f]开头(但不固定),不能单靠这个判断,得看协议约定
最稳妥的方式是和服务端对齐压缩封装方式,别混用 gzip 和 deflate 接口。










