电话
400 9058 355
必须显式设置CURLOPT_ENCODING为''才能自动解压gzip响应,否则返回乱码;file_get_contents不支持自动解压,需改用cURL或手动gzdecode;调试应结合curl_getinfo验证响应头与magic bytes。
PHP 的 curl_setopt 默认不会自动处理 gzip 响应解压,即使服务端返回了 Content-Encoding: gzip。不设 CURLOPT_ENCODING,你收到的就是一串乱码二进制数据,json_decode 直接失败,file_get_contents 也读不出有效文本。
正确做法是传空字符串给 CURLOPT_ENCODING,让 cURL 自动协商支持的压缩方式:
curl_setopt($ch, CURLOPT_ENCODING, '');
''(空字符串):cURL 自动在请求头加 Accept-Encoding: gzip, deflate,并自动解压响应体'gzip':只声明支持 gzip,但部分旧版 cURL 可能不自动解压,需手动调用 gzdecode()
'identity' 或忽略该选项,否则压缩响应原样返回所谓“PHP 模拟 POST 请求 gzip 压缩”,通常指两种情况:一种是发请求时把 POST body 压缩(服务端主动要求),另一种是收响应时解压(更常见)。绝大多数 API(如微信、支付宝、云厂商接口)只要求客户端接收 gzip 响应,**不要求你发 gzip body**。
如果你真遇到服务端明确要求上传 gzip 压缩的 JSON 或表单数据(极少见),需手动压缩并设置请求头:
$data = gzencode(json_encode($payload), 9);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Encoding: gzip',
'Content-Length: ' . strlen($data)
]);
gzencode()(不是 gzcompress() 或 gzdeflate()),它生成标准 gzip 格式Content-Length,因为 gzencode 后长度变了别试图用 stream_context_create 配 http 选项来让 file_get_contents 解 gzip。PHP 的流封装器对 Accept 支持极弱,
file_get_contents 返回的永远是原始响应体,哪怕 header 里写了 Content-Encoding: gzip。
这是硬限制,不是配置问题。要可靠解压,只有两个选择:
curl 并设 CURLOPT_ENCODING => ''
gzdecode()(注意:仅适用于 PHP ≥ 5.4,且响应确实是 gzip 格式)例如手动解压:
$raw = file_get_contents($url, false, $context);
if (strpos($http_response_header[0], '200') !== false && preg_grep('/^Content-Encoding:.*gzip/i', $http_response_header)) {
$body = @gzdecode($raw);
}
光看 curl_exec 返回的内容不够,压缩是否生效、服务端是否真的返回了 gzip,得查响应头。用 curl_getinfo($ch, CURLINFO_HEADER_OUT) 看请求头是否带 Accept-Encoding,用 curl_getinfo($ch, CURLINFO_CONTENT_TYPE) 和 CURLINFO_CONTENT_ENCODING 看服务端实际返回了什么。
CURLINFO_CONTENT_ENCODING 返回 gzip 才说明服务端确实压缩了\x1f\x8b(gzip magic bytes),说明服务端压缩了但没写 header —— 这属于服务端 bug,你得手动 gzdecode
curl_setopt($ch, CURLOPT_HEADER, true) 会把 header 和 body 混在一起,不方便解析,优先用 curl_getinfo
gzip 响应体的边界很模糊:header 可能缺失、压缩级别不一致、服务端中间件可能提前解压又不重写 header。最稳妥的方式,始终以实际字节流特征(magic bytes) + Content-Encoding header + 文档约定三者交叉验证。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...