使用PHP解码通过cURL获取的gzipped网页

65

我正在使用curl获取一个gzip压缩的网页,但当我将获取到的内容输出到浏览器时,我只得到了原始的gzip数据。如何在PHP中解码数据?

我发现的一种方法是将内容写入临时文件,然后...

$f = gzopen($filename,"r");
$content = gzread($filename,250000);
gzclose($f);

...但是,伙计们,必须有更好的方法。

编辑:这不是一个文件,而是由Web服务器返回的压缩的HTML页面。


文件本身是否已经被压缩,还是服务器在传输时进行了压缩? - Artelius
2
你可以发送正确的头信息,让浏览器正确识别,而不是解码gzip数据吗?或者,如果你一开始就不想要它被压缩,可以通过设置CURLOPT_ENCODING为“identity”来告诉cURL不要请求gzip数据。 - nobody
有一个名为gzdecode的PHP函数,适用于字符串而非文件。 - pgr
2个回答

156

以下命令启用cURL的“自动编码”模式,在此模式下,它将通过Accept-Encoding头告诉服务器它支持哪些编码方法,并自动为您解压缩响应:

// Allow cURL to use gzip compression, or any other supported encoding
// A blank string activates 'auto' mode
curl_setopt($ch, CURLOPT_ENCODING , '');
如果你想要强制使用头部信息Accept-Encoding: gzip,可以使用以下命令:
// Allow cURL to use gzip compression, or any other supported encoding
curl_setopt($ch, CURLOPT_ENCODING , 'gzip');

阅读更多,请查看PHP文档:curl_setopt

感谢评论者帮助改进此答案。


23
请注意,此选项会在请求中设置“Accept-Encoding: gzip”头,并且如果响应已经压缩(但也可能未被压缩),它会对其进行解压缩,因此这确实是您需要做的全部内容。 - Synchro
CURL的完美解决方案。 - The Onin
15
将其设置为'gzip'将始终发送Accept-Encoding: gzip,即使您的PHP版本不支持解压缩gzip(那么您将获取压缩数据)。如果您将其设置为空字符串'',curl将自动宣告并解码它支持的所有编码。 - AndreKR
@AndreKR - 太棒了。我在文档中读到了这句话:“如果设置为空字符串“”,则发送包含所有支持的编码类型的标头。” - But those new buttons though..
1
我根据上面的评论,对你的优秀答案进行了更新,使其更加详尽。希望这样可以吧! - Simon East

5
多功能的GUNZIP函数:
   function gunzip($zipped) {
      $offset = 0;
      if (substr($zipped,0,2) == "\x1f\x8b")
         $offset = 2;
      if (substr($zipped,$offset,1) == "\x08")  {
         # file_put_contents("tmp.gz", substr($zipped, $offset - 2));
         return gzinflate(substr($zipped, $offset + 8));
      }
      return "未知格式";
   }  
将该函数与CURL集成的示例:
      $headers_enabled = 1;
      curl_setopt($c, CURLOPT_HEADER,  $headers_enabled)
      $ret = curl_exec($c);
if ($headers_enabled) { # file_put_contents("preungzip.html", $ret);
$sections = explode("\x0d\x0a\x0d\x0a", $ret, 2); while (!strncmp($sections[1], 'HTTP/', 5)) { $sections = explode("\x0d\x0a\x0d\x0a", $sections[1], 2); } $headers = $sections[0]; $data = $sections[1];
if (preg_match('/^Content-Encoding: gzip/mi', $headers)) { printf("找到gzip头\n"); return gunzip($data); } }
return $ret;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接