使用PHP cURL无法获取Content Encoding的技术求助
问题
使用PHP的cURL库获取目标资源的Content Type和Content Encoding时,Content Type能正常获取,但Content Encoding始终为空。测试URL https://affiliatefix.com/sitemap-1.xml 实际返回gzip编码,但无法通过代码捕获到。
原代码:
function get_content_type_curl($url_content_type) { $agent_content_type = $_SERVER['HTTP_USER_AGENT']; $ch_content_type = curl_init(); curl_setopt($ch_content_type, CURLOPT_URL, $url_content_type); curl_setopt($ch_content_type, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch_content_type, CURLOPT_HEADER, 0); curl_setopt($ch_content_type, CURLOPT_NOBODY, 1); curl_setopt($ch_content_type, CURLOPT_USERAGENT, $agent_content_type); curl_setopt($ch_content_type, CURLOPT_FOLLOWLOCATION, 1); curl_exec($ch_content_type); $content_type = curl_getinfo($ch_content_type, CURLINFO_CONTENT_TYPE); $content_encoding = defined('CURLINFO_CONTENT_ENCODING') ? curl_getinfo($ch_content_type, CURLINFO_CONTENT_ENCODING) : ''; //$content_encoding = curl_getinfo($ch_content_type, CURLINFO_CONTENT_ENCODING); curl_close($ch_content_type); return array("content_type" => $content_type, "content_encoding" => $content_encoding); } $result = get_content_type_curl("https://affiliatefix.com/sitemap-1.xml"); echo $result["content_type"] . "\n"; if (!empty($result["content_encoding"])) { echo $result["content_encoding"] . "\n"; } /**if (strpos($result["content_encoding"], "gzip") !== false) { echo $result["content_encoding"] . "\n"; } else { echo "No encoding".$result["content_encoding"] . "\n"; }**/
原因分析
- HEAD请求局限性:代码设置
CURLOPT_NOBODY = 1会发送HEAD请求,部分服务器对HEAD请求的响应不会返回Content-Encoding头,因为HEAD仅用于获取元数据,服务器可能省略编码相关信息。 - 未声明编码支持:没有向服务器发送
Accept-Encoding请求头,服务器默认不会返回编码信息,即使资源本身是压缩状态。 - 版本兼容性:
CURLINFO_CONTENT_ENCODING常量需要cURL 7.21.0+和PHP 5.3.10+支持,环境版本过低会导致该常量未定义,返回空值。
解决方案
方案1:改用GET请求解析响应头
去掉CURLOPT_NOBODY,设置CURLOPT_HEADER = 1发送GET请求,从响应头中提取编码信息:
function get_content_info($url) { $agent = $_SERVER['HTTP_USER_AGENT']; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 1); // 包含响应头 curl_setopt($ch, CURLOPT_NOBODY, 0); // 发送GET请求 curl_setopt($ch, CURLOPT_USERAGENT, $agent); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Accept-Encoding: gzip, deflate' // 声明支持的编码 ]); $response = curl_exec($ch); $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $headers = substr($response, 0, $header_size); $content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); // 解析Content-Encoding $content_encoding = ''; if (preg_match('/Content-Encoding:\s*(.*?)\s*$/mi', $headers, $matches)) { $content_encoding = trim($matches[1]); } curl_close($ch); return [ "content_type" => $content_type, "content_encoding" => $content_encoding ]; } $result = get_content_info("https://affiliatefix.com/sitemap-1.xml"); echo $result["content_type"] . "\n"; if (!empty($result["content_encoding"])) { echo $result["content_encoding"] . "\n"; }
方案2:保留HEAD请求,添加编码支持头
继续使用HEAD请求,补充Accept-Encoding头告知服务器支持的编码类型:
function get_content_type_curl($url_content_type) { $agent_content_type = $_SERVER['HTTP_USER_AGENT']; $ch_content_type = curl_init(); curl_setopt($ch_content_type, CURLOPT_URL, $url_content_type); curl_setopt($ch_content_type, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch_content_type, CURLOPT_HEADER, 0); curl_setopt($ch_content_type, CURLOPT_NOBODY, 1); curl_setopt($ch_content_type, CURLOPT_USERAGENT, $agent_content_type); curl_setopt($ch_content_type, CURLOPT_FOLLOWLOCATION, 1); // 添加Accept-Encoding头 curl_setopt($ch_content_type, CURLOPT_HTTPHEADER, [ 'Accept-Encoding: gzip, deflate' ]); curl_exec($ch_content_type); $content_type = curl_getinfo($ch_content_type, CURLINFO_CONTENT_TYPE); $content_encoding = defined('CURLINFO_CONTENT_ENCODING') ? curl_getinfo($ch_content_type, CURLINFO_CONTENT_ENCODING) : ''; curl_close($ch_content_type); return array("content_type" => $content_type, "content_encoding" => $content_encoding); } $result = get_content_type_curl("https://affiliatefix.com/sitemap-1.xml"); echo $result["content_type"] . "\n"; if (!empty($result["content_encoding"])) { echo $result["content_encoding"] . "\n"; }
额外注意事项
- 检查PHP和cURL版本,确保
CURLINFO_CONTENT_ENCODING常量可用; - 部分服务器对不同User-Agent返回不同响应头,确保使用的User-Agent符合服务器预期;
- 方案1中若资源较大,可设置
CURLOPT_RANGE = '0-0'仅请求部分内容,减少带宽消耗。
内容的提问来源于stack exchange,提问作者Mehul Kumar
相关产品推荐
相关产品推荐

