gzencode 是接口大体积 JSON 数据最直接的压缩方式,需手动调用并设置 Content-Encoding: gzip 和 Vary: Accept-Encoding 响应头,且应校验客户端 Accept-Encoding 请求头后再压缩,避免乱码或缓存污染。

接口返回数据太大时,gzencode 是最直接的压缩方式
PHP 原生不自动压缩响应体,必须手动处理。如果接口返回 JSON 数据体积常超 100KB,用 gzencode 压缩后通常能减少 60%–80% 体积,且客户端(如 curl、现代浏览器、App)普遍支持 gzip 解压。
关键点:压缩必须配合正确的 HTTP 头,否则客户端无法识别或解压失败。
- 先调用
gzencode($data, 9),第二个参数用9表示最高压缩比(CPU 换体积,小数据不必强求) - 必须设置
Content-Encoding: gzip响应头,缺一不可 - 原始
Content-Type(如application/json)仍要保留,不能删 - 不要对已压缩过的数据(比如图片、PDF)再套
gzencode,无效还增开销
客户端没发 Accept-Encoding: gzip 时,别硬压
不是所有请求都支持解压。有些旧设备、测试工具(如 Postman 默认关 gzip)、或中间代理可能忽略或错误处理 Content-Encoding。强行压缩会导致乱码或解析失败。
安全做法是检查请求头再决定是否压缩:
立即学习“PHP免费学习笔记(深入)”;
if (stripos($_SERVER['HTTP_ACCEPT_ENCODING'] ?? '', 'gzip') !== false) {
$encoded = gzencode($json, 9);
header('Content-Encoding: gzip');
header('Vary: Accept-Encoding');
echo $encoded;
} else {
echo $json;
}
Vary: Accept-Encoding 这一行很重要,它告诉 CDN 或代理:这个响应内容取决于客户端是否接受 gzip,避免缓存污染。
用 ob_gzhandler 看似简单,但容易和框架/输出缓冲冲突
PHP 内置的 ob_gzhandler 可以自动压缩输出,启用只需一行:ob_start('ob_gzhandler');。但它依赖输出缓冲(output buffering),而 Laravel、ThinkPHP 等框架常自带缓冲层,或已调用过 ob_start(),此时再叠用会报 Warning: ob_start(): output handler 'ob_gzhandler' cannot be used twice。
- 纯脚本接口(无框架)可用,但需确保没其他
ob_*调用在前 - 框架项目中优先用手动
gzencode,可控性高,不依赖执行顺序 -
ob_gzhandler不支持细粒度压缩级别控制,默认用中等压缩(约6),不如gzencode($data, 9)灵活
压缩后记得关掉 Content-Length 自动计算
PHP 在开启 output_buffering 或使用 ob_gzhandler 时,有时会自动加 Content-Length 响应头——但那是未压缩前的长度,和实际发送的 gzip 数据长度不一致,导致客户端卡住或截断。
手动压缩时,务必显式清除或跳过该头:
// 压缩前先关掉可能存在的 Content-Length
header_remove('Content-Length');
// ……然后压缩并输出
header('Content-Encoding: gzip');
echo gzencode($json, 9);
某些 Nginx 配置(如 gzip on)也会干扰 PHP 层压缩,建议在 Nginx 中关闭 gzip,把压缩逻辑收归 PHP 统一控制,避免双重压缩或头冲突。



















