【问题标题】:Uncompress gzip compressed http response解压缩 gzip 压缩的 http 响应
【发布时间】:2012-02-12 07:54:13
【问题描述】:

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

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

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

我知道还有另一个函数可以解压缩 gzipped 数据gzdecode(),但它不包含在我的 PHP 版本中(也许它只在 SVN 上可用)。

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

您知道在 PHP 中解压缩 gzip 数据的任何其他方法吗?或者为什么 gzuncompress() 会输出警告? gzuncompress() 没有按预期工作是荒谬的。

注意事项: 问题肯定与 PHP 有关:HTTP 请求是向 Tumblr API 发出的,该 API 给出了良好编码的响应。

【问题讨论】:

  • 你知道他们为什么建议使用file_get_contents而不是cUrl吗?
  • 不,我不知道,他们说“这样更好”。我可以回到 cUrl,但我还是对 gzuncompress() 问题感到好奇。
  • 是不是因为数据也是base64编码的?
  • 您确定file_get_contents 没有为您解压吗?这是一个很长的镜头,我知道...尝试转储文件的内容并检查文件开头的 gzip 幻数0x1f8b
  • 不,即使添加了 base64_decode() 我也会遇到同样的错误。

标签: php


【解决方案1】:

发现这对我有用: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));
    }
}

【讨论】:

  • 漂亮,我一直在寻找这个
  • 看来gzinflate不如gzdecode灵活。适用于 gzdecode 但不适用于 gzinflate 的示例:cdn.misterwhat.com/mwuk.min.gz.css?ver=3.1
  • 是的,这行得通。这应该是我公认的答案
【解决方案2】:

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

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

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

【讨论】:

  • 我正在开发一个开源库,所以我不能强迫用户安装upgradephp。库安装应该尽可能简单,所以我转而使用具有内置 gzip 支持的 cUrl。
  • 嗯,什么?如果您不想一起发布整个 upgradephp sn-p,您可以复制并粘贴该单个函数实现。
  • Mario,感谢您的建议,但我刚刚转向 cUrl,离开了 file_get_contents() 实现。你确定从 upgradephp 导入 gzdecode() 可以在没有任何其他依赖的情况下工作吗?
  • 使用 upgrade.php 有效。就像 HTML5 的 javascript 垫片一样。完美的!谢谢。
  • 那个 upgradephp 项目太棒了。我为它添加了一个 Github 克隆:github.com/Polycademy/upgradephp
【解决方案3】:

在解压缩数据之前,您需要对其进行组装。 所以如果标题包含

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);
...

【讨论】:

    猜你喜欢
    • 2012-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    相关资源
    最近更新 更多