Подтвердить что ты не робот

Uncompress gzip сжатый HTTP-ответ

Я использую функцию 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

Я знаю, что есть еще одна функция, способная распаковывать данные gzipped gzdecode(), но она не включена в мою версию PHP (возможно, она доступна только в SVN).

Я знаю, что cUrl декодирует gzip-поток "на лету" (без каких-либо проблем), но кто-то предложил мне использовать file_get_contents() вместо cUrl.

Знаете ли вы какой-либо другой способ распаковать gzip-данные на PHP или почему gzuncompress() выводит предупреждение? Абсурдно, что gzuncompress() работает не так, как ожидалось.

Примечания: Проблема, конечно же, в PHP: HTTP-запрос сделан в Tumblr API, который дает хорошо закодированный ответ.

4b9b3361

Ответ 1

gzuncompress не будет работать для кодировки gzip. Это функция декомпрессии для архивов .Z.

В руководстве перечислены несколько обходных путей для отсутствующего gzdecode() # 82930 или просто используйте один из upgradephp или временный файл временного файла gzopen.

Другим вариантом будет принудительное кодирование deflate с заголовком Accept-Encoding:, а затем с помощью gzinflate() для декомпрессии.

Ответ 2

Нашел это для меня: 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));
    }
}

Ответ 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 дефлируется, используйте gzdeflate

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