compressionstream 是 streams api 中用于浏览器端实时 gzip/deflate 压缩的原生接口,主流浏览器已稳定支持 gzip;需显式指定类型、处理异常、转换字节流、合并 uint8array 块,并注意小数据膨胀及服务端解压配置。

CompressionStream 是 HTML5(更准确说是 Streams API 的一部分)中用于在浏览器端实时压缩数据的原生接口,它支持 gzip 和 deflate 两种格式。不过需注意:截至 2024 年,CompressionStream 的 gzip 支持已在主流浏览器(Chrome 103+、Edge 103+、Firefox 116+、Safari 16.4+)中稳定可用,但仍有兼容性细节需处理。
确认浏览器支持并创建 CompressionStream
不是所有环境都默认启用 gzip 压缩,需显式指定 "gzip" 类型,并检查构造是否成功:
- 使用
new CompressionStream("gzip")创建压缩流;若浏览器不支持该类型,会抛出DOMException(如"InvalidStateError"或"NotSupportedError") - 建议包裹在
try...catch中,并降级为纯文本或禁用压缩 - 注意:
"deflate"行为在不同浏览器中可能不一致(例如 Firefox 使用 zlib 封装,Chrome 使用 raw deflate),生产环境推荐统一用"gzip"
将数据写入压缩流并读取压缩后结果
CompressionStream 本身是 TransformStream,需连接可读流(ReadableStream)与可写流(WritableStream)。典型流程是:
- 把原始数据(如字符串、ArrayBuffer、Blob)转为
ReadableStream(可用stream = new ReadableStream({ start(c) { c.enqueue(data); c.close(); } })) - 通过
.pipeThrough(new CompressionStream("gzip"))接入压缩流 - 用
.getReader().read()获取压缩后的Uint8Array块 - 最终拼接所有块得到完整 gzip 字节流(即标准 RFC 1952 格式,含 gzip 头/尾)
示例关键代码:
async function gzipString(str) {
const encoder = new TextEncoder();
const stream = new ReadableStream({
start(controller) {
controller.enqueue(encoder.encode(str));
controller.close();
}
});
const compressedStream = stream.pipeThrough(new CompressionStream("gzip"));
const reader = compressedStream.getReader();
const chunks = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
}
// 合并所有 Uint8Array
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
const result = new Uint8Array(totalLength);
let offset = 0;
for (const chunk of chunks) {
result.set(chunk, offset);
offset += chunk.length;
}
return result; // 返回 gzip 压缩后的 Uint8Array
}
注意事项与常见问题
实际使用中容易忽略几个关键点:
-
输入必须是字节流:不能直接传字符串给
CompressionStream,必须先用TextEncoder或File.arrayBuffer()转为Uint8Array -
输出无自动 Base64 编码:返回的是二进制
Uint8Array,如需上传或显示,需手动转成base64(用btoa(String.fromCharCode(...))或FileReader)或保持为Blob - 小数据压缩可能变大:gzip 有固定头部(至少 18 字节),短于约 20 字符的文本压缩后反而更大,建议设置最小长度阈值(如 ≥100 字节再压缩)
-
无法控制压缩级别:浏览器不暴露
level参数,压缩强度由引擎内部决定(通常为默认中等强度)
结合 Blob 或 Fetch 上传的实用场景
最常见用途是前端采集日志、表单数据或分析事件后,在发送前压缩:
- 将压缩结果转为
Blob:new Blob([uint8Array], { type: "application/gzip" }) - 上传时设置请求头:
headers: { "Content-Encoding": "gzip" },后端需识别并解压(如 Express 配compression()中间件) - 服务端必须明确支持接收 gzip 编码体(很多默认只解压
req.body,需额外配置如bodyParser.raw({ type: "application/gzip" }))
不复杂但容易忽略细节,实际接入时建议先用 console.log 输出压缩前后长度比对效果。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











