php用gzencode()压缩响应体需手动设置content-encoding: gzip头,否则浏览器无法自动解压;它不依赖输出缓冲,比ob_gzhandler更可控,但必须校验accept-encoding并配对设置vary头。

PHP后台用 gzencode() 做响应体压缩最直接
浏览器能自动解压,服务端不用额外处理 Accept-Encoding,gzencode() 生成标准 gzip 格式二进制数据,比 ob_gzhandler 更可控。它不依赖输出缓冲开关状态,也不受 php.ini 中 zlib.output_compression 干扰。
常见错误是直接 echo 压缩后数据却不设 header,导致前端拿到乱码。必须配对设置 Content-Encoding: gzip,否则浏览器当普通文本解析。
- 只压缩纯文本类响应(JSON、HTML、XML),不要对图片、PDF 等已压缩格式再压
- 压缩前先
json_encode()或拼好字符串,gzencode()只接受 string 类型 - 注意内存:大数组直接
gzencode(json_encode($big_data))可能触发内存溢出,建议分块或加@抑制警告
// 示例:返回压缩后的 JSON
$data = ['users' => array_fill(0, 1000, ['id' => 1, 'name' => 'test'])];
$json = json_encode($data);
$compressed = gzencode($json, 9); // 9 是最高压缩比
header('Content-Type: application/json');
header('Content-Encoding: gzip');
header('Content-Length: ' . strlen($compressed));
echo $compressed;
什么时候该用 ob_start('ob_gzhandler')
适合整页 HTML 输出且不想改业务逻辑的场景——比如老项目套了 Smarty 或原生 PHP 模板,所有输出都走 echo 或 print。它在输出缓冲层自动判断是否支持 gzip,并决定是否压缩。
但隐患明显:如果中间某处调用了 ob_flush()、flush() 或提前输出了内容(比如空格、BOM),就会导致 ob_gzhandler 失效并报 “headers already sent” 错误。
- 必须放在脚本最开头,任何输出之前(包括 UTF-8 BOM)
- php.ini 中
zlib.output_compression开着时,ob_gzhandler会被绕过,行为不可控 - 无法对特定接口单独开关,是全局限制
API 接口返回压缩数据要检查 Accept-Encoding
客户端不一定支持 gzip,比如某些 IoT 设备或旧版 curl 默认不带请求头。硬编码压缩会直接让它们解析失败。
正确做法是先读取 $_SERVER['HTTP_ACCEPT_ENCODING'],再决定是否压缩和返回哪个 header:
- 匹配到
gzip才调用gzencode(),否则原样输出 - 注意大小写:实际值可能是
GZIP、gzip,deflate,建议用stripos()判断 - 别忘了同时设置
Vary: Accept-Encoding,否则 CDN 或代理可能缓存错版本
$encoding = $_SERVER['HTTP_ACCEPT_ENCODING'] ?? '';
if (stripos($encoding, 'gzip') !== false) {
header('Content-Encoding: gzip');
header('Vary: Accept-Encoding');
echo gzencode($payload);
} else {
echo $payload;
}
压缩比和性能的实际取舍
gzencode($data, 1) 和 gzencode($data, 9) 在小数据上差别几乎为零,但 CPU 时间差 3–5 倍。日常 API 返回几 KB 到几百 KB 的 JSON,用默认等级(-1)或 4–6 就够了。
真正影响性能的是重复压缩:比如同一份数据被多个请求反复 gzencode(),应该考虑加一层简单缓存(apcu 或文件),键名带上压缩等级和原始 hash。
- 不要在循环里调用
gzencode()处理单条记录——那是设计问题,不是压缩问题 - 启用 OPcache 后,
gzencode()本身开销极低,瓶颈通常在序列化或数据库查询 - 如果用了 Swoole 或 RoadRunner,注意
gzencode()是线程安全的,但共享内存缓存需自行加锁
压缩不是银弹。HTTP/2 下多路复用降低了传输收益,而 CPU 和内存成本始终存在。先测真实 payload 大小和用户网络环境,再决定压不压、怎么压。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











