Я использую функцию 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, который дает хорошо закодированный ответ.
gzuncompress
не будет работать для кодирования gzip
. Это функция декомпрессии для архивов .Z
.
В руководстве перечислены некоторые обходные пути для отсутствующего gzdecode()
# 82930 или просто используйте один из upgradephp
или временный файл временного файла gzopen.
Другой вариант – принудительное кодирование с gzinflate()
с заголовком Accept-Encoding:
а затем с помощью gzinflate()
для декомпрессии.
Нашел это для меня: 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)); } }
Перед распаковкой данных вам необходимо собрать его. Поэтому, если заголовок содержит
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); ...