解压缩gzip压缩的http响应

时间:2012-01-17 13:59:09

标签: php

我正在使用php的file_get_contents()函数来执行HTTP请求。为了节省带宽,我决定使用"Accept-Encoding: gzip"添加stream_context_create()标头。

显然,file_get_contents()输出一个gzip编码的字符串,所以我使用gzuncompress()来解码编码的字符串,但是我得到一个错误,数据作为参数传递。

[...] PHP Warning: gzuncompress(): data error in /path/to/phpscript.php on line 26

我知道还有另一个功能可以解压缩gzip压缩数据gzdecode(),但它不包含在我的PHP版本中(可能只在SVN上提供)。

我知道cUrl动态解码gzip流(没有任何问题)但有人建议我使用file_get_contents()而不是cUrl。

您是否知道在PHP中解压缩gzip压缩数据的其他方法或为什么gzuncompress()输出警告? gzuncompress()无法正常工作是荒谬的。

注意: 问题当然是关于PHP:HTTP请求是针对Tumblr API的,它提供了良好编码的响应。

3 个答案:

答案 0 :(得分:30)

发现这对我有用:http://www.php.net/manual/en/function.gzdecode.php#106397

可选择尝试:http://digitalpbk.com/php/file_get_contents-garbled-gzip-encoding-website-scraping

if ( ! function_exists('gzdecode'))
{
    /**
     * Decode gz coded data
     * 
     * http://php.net/manual/en/function.gzdecode.php
     * 
     * Alternative: http://digitalpbk.com/php/file_get_contents-garbled-gzip-encoding-website-scraping
     * 
     * @param string $data gzencoded data
     * @return string inflated data
     */
    function gzdecode($data) 
    {
        // strip header and footer and inflate

        return gzinflate(substr($data, 10, -8));
    }
}

答案 1 :(得分:13)

gzuncompress不适用于gzip编码。这是.Z档案的解压缩功能。

本手册列出了缺少gzdecode()#82930的一些解决方法,或者只使用upgradephp中的一个或gzopen临时文件解决方法。

另一种选择是使用deflate标题强制Accept-Encoding:编码,然后使用gzinflate()进行解压缩。

答案 2 :(得分:1)

在解除数据之前,您需要组装它。 所以如果标题包含

Transfer-Encoding: chunked

你需要解开它。

function http_unchunk($data) {
    $res=[];
    $p=0; $n=strlen($data);
    while($p<$n) {
        if (preg_match("/^([0-9A-Fa-f]+)\r\n/",substr($data,$p,18),$m)) {
            $sz=hexdec($m[1]); $p+=strlen($m[0]);
            $res[]=substr($data,$p,$sz); $p+=$sz+2;
        } else {
            break;
        }
    }
    return implode('',$res);
}

如果Content-Encoding是gzip或x-gzip或x-compress使用gzdecode 如果Content-Encoding是deflate,请使用gzdeflate

...
if ($chunked) $body=http_unchunk($body);
if ($gzip) $body=gzdecode($body);
if ($deflate) $body=gzdeflate($body);
...