php 解压缩 gzip 压缩的 http 响应

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8895852/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 05:44:38  来源:igfitidea点击:

Uncompress gzip compressed http response

php

提问by Fabio Buda

I'm using php's file_get_contents()function to do a HTTP request. To save bandwidth I decided to add the "Accept-Encoding: gzip"header using stream_context_create().

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

Obviously, file_get_contents()outputs a gzip encoded string so I'm using gzuncompress()to decode the encoded string but I get an error with data passed as argument.

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

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

I know there is another function able to decompress gzipped data gzdecode()but it isn't included in my PHP version (maybe it is only available on SVN).

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

I know that cUrl decodes gzip stream on the fly (without any problem) but someone suggested me to use file_get_contents()instead of cUrl.

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

Do you know any other way to decompress gzipped data in PHP or why gzuncompress()outputs a Warning? It is absurd that gzuncompress()doesn't work as expected.

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

Notes: The problem is certainly about PHP: the HTTP request is made to Tumblr API that give a well-encoded response.

注意:问题肯定是关于 PHP:HTTP 请求是向 Tumblr API 发出的,它给出了一个编码良好的响应。

采纳答案by mario

gzuncompresswon't work for the gzipencoding. It's the decompression function for the .Zarchives.

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

The manual lists a few workarounds for the missing gzdecode()#82930, or just use the one from upgradephp, or the gzopen temp file workaround.

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

Another option would be forcing the deflateencoding with the Accept-Encoding:header and then using gzinflate()for decompression.

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

回答by Mike

Found this working for me: http://www.php.net/manual/en/function.gzdecode.php#106397

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

Optionally try: http://digitalpbk.com/php/file_get_contents-garbled-gzip-encoding-website-scraping

可选择尝试: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));
    }
}

回答by kovserg

Before decomress data you need to assemble it. So if header contains

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

Transfer-Encoding: chunked

you need to unchank it.

你需要解开它。

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

if Content-Encoding is gzip or x-gzip or x-compress use gzdecode if Content-Encoding is deflate use gzdeflate

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