HTTPQUERY
English

Content-Encoding

用法

Content-Encoding 头按应用顺序列出对表示数据所应用的编码。客户端反向执行这条编码链以重建原始内容。压缩是最常见的用例,它以服务器和客户端两端的 CPU 时间为代价来减小传输体积。

Accept-Encoding 请求头声明客户端支持哪些编码。服务器从列表中选择一种编码,并在 Content-Encoding 响应头中表明其选择。当不存在可接受的编码时,服务器以未压缩的形式发送响应。

当存在 Content-Encoding 时,Content-Length 等元数据头指的是编码后的形式,而非原始资源。JPEG、PNG 和 ZIP 等预压缩的媒体格式已包含内部压缩,再经过一次编码几乎没有收益。对这些格式应用内容编码会浪费 CPU,有时还会增加传输体积。

Content-Encoding 头描述的是表示编码,这是资源的端到端属性。这与 Transfer-Encoding 不同,后者是一种逐跳属性,在每个网络中间节点上应用和移除。

注意

gzip 仍然是部署最广泛的编码。Brotli 对静态文本内容提供最佳的压缩比。Zstandard 在快速压缩和高压缩比之间取得平衡,并有广泛的浏览器支持。

注意

资源的原始媒体类型由 Content-Type 头描述。Content-Encoding 反映的是当前表示的压缩状态,而非底层内容的格式。

gzip

采用 32 位 CRC 的 Lempel-Ziv 编码(LZ77)算法。gzip 于 1996 年引入,至今仍是 Web 上支持最广泛的编码。服务器也识别 x-gzip 作为别名。

compress

Lempel-Ziv-Welch(LZW)算法,最初来自 UNIX 的 compress 程序。专利问题导致该算法衰落,没有任何现代浏览器支持 compress。

deflate

包裹 deflate 算法的 zlib 结构。所有浏览器都支持,但在很大程度上已被 gzip 和更新的算法取代。

br

Brotli 算法。Brotli 通过使用内置的常见 Web 术语静态字典,达到了比 gzip 更高的压缩比,尤其是在基于文本的 Web 内容上。Brotli 需要 HTTPS。所有主流浏览器都支持。

zstd

Zstandard 算法。Zstandard 以与 gzip 相当的速度进行压缩,同时达到接近 Brotli 的压缩比。该算法支持从 1(最快)到 22(最高压缩比)的可配置压缩级别,让服务器可以用 CPU 时间换取更小的负载。无论使用何种压缩级别,解压速度都始终保持很快。

Zstandard 还支持基于字典的压缩,使用一个在代表性内容上训练出的预共享字典可进一步减小负载体积。Use-As-Dictionary 头和 Compression Dictionary Transport 机制正是构建于这一能力之上。

由基于 Chromium 的浏览器、Firefox 和较新版本的 Safari 支持。

dcb

字典压缩的 Brotli。作为 Compression Dictionary Transport 规范的一部分定义。客户端和服务器通过 Use-As-Dictionary 和 Available-Dictionary 头协商一个共享字典。服务器使用带共享字典的 Brotli 压缩响应,并将编码标识为 dcb。

dcz

字典压缩的 Zstandard。使用与 dcb 相同的字典传输机制,只是用 Zstandard 算法代替 Brotli。服务器使用协商好的字典进行压缩,并将编码标识为 dcz。

示例

一个用 gzip 压缩的响应。这是 Web 上最常见的编码,拥有普遍的浏览器支持。

Content-Encoding: gzip

一个用 Brotli 压缩的响应。对于 HTML、CSS 和 JavaScript 资源,Brotli 通常比 gzip 产生更小的负载。

Content-Encoding: br

一个用 Zstandard 压缩的响应。选择 Zstandard 的服务器可享受快速压缩以及与 Brotli 相当的压缩比。

Content-Encoding: zstd

按顺序应用的多种编码。资源先用 deflate 编码,然后用 gzip 编码。客户端以相反的顺序解码:先 gzip,后 deflate。

Content-Encoding: deflate, gzip

一个使用字典压缩 Zstandard 的响应。客户端此前通过 Use-As-Dictionary 头收到了一个字典,并在 Available-Dictionary 请求头中声明了该字典。服务器针对这个共享字典压缩了响应。

Content-Encoding: dcz

故障排查

与压缩相关的失败表现为浏览器解码错误、下载文件损坏或响应以未压缩形式到达。

双重压缩产生损坏的响应。反向代理或 CDN 对来自源站的已压缩响应再次压缩,产生客户端无法解码的无效负载。检查 Content-Encoding 头是否有诸如 gzip, gzip 的堆叠值。在 nginx 中,当源站已经压缩时禁用代理压缩:

proxy_set_header Accept-Encoding "";

在 Cloudflare 中,当源站发送预压缩响应时,在 Speed 设置中禁用”Brotli”。

浏览器显示 ERR_CONTENT_DECODING_FAILED。当 Content-Encoding 头声明的编码与实际主体内容不匹配时会出现该错误。常见原因:源站发送了带 Content-Encoding: gzip 的未压缩主体,或中间件剥离了编码却保留了头。运行 curl -v -H “Accept-Encoding: gzip” https://example.re,检查原始主体是否与声明的编码匹配。通过 gunzip 管道验证:curl -s —compressed https://example.re | head。

压缩后 Content-Length 不匹配。Content-Length 值必须反映压缩后的主体大小,而非原始大小。不匹配会导致浏览器截断或拒绝响应。使用 nginx gzip on 时,nginx 会自动重新计算 Content-Length。在压缩运行之前设置 Content-Length 的中间件会导致该问题。将 Content-Length 的赋值移到压缩之后,或移除该头让服务器使用分块 Transfer-Encoding。

尽管有服务器配置却未应用压缩。服务器在压缩前会检查 Accept-Encoding 请求头。缺失或为空的 Accept-Encoding 意味着不压缩。某些代理会从转发的请求中剥离 Accept-Encoding。在 nginx 中,确认设置了 gzip on 并且 MIME 类型匹配:

gzip on;
gzip_types text/plain application/json
           text/css application/javascript;

在 Apache 中,启用 mod_deflate 并确认过滤器已应用:

AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE application/json

提供预压缩文件以获得更好的性能。在每个请求上压缩会浪费 CPU。改为从磁盘提供预压缩的静态文件。在 nginx 中,启用 gzip_static on 以在原始文件旁提供 .gz 文件。在 Apache 中,启用 MultiViews 或使用 mod_rewrite 将请求映射到 .gz 或 .br 变体。确保预压缩文件在部署期间与原始文件保持同步。