Почему функция PHP gzuncompress() может работать неправильно?

PHP имеет собственную функцию для работы с архивами gzip. Я написал следующий код:

error_reporting(E_ALL);
$f = file_get_contents('http://spiderbites.nytimes.com/sitemaps/www.nytimes.com/sitemap.xml.gz');
echo $f;
$f = gzuncompress($f);
echo "<hr>";
echo $f;

Первое эхо обычно выводит сжатый файл с правильным заголовком (по крайней мере, первые два байта верны). Если бы я загрузил этот файл с помощью своего браузера, я бы легко его распаковал.

Однако gzuncompress бросил Warning: gzuncompress(): data error in /home/path/to/script.php on line 5

Может ли кто-нибудь указать мне правильное направление для решения этой проблемы?

ИЗМЕНИТЬ:

Часть вывода phpinfo()

введите здесь описание изображения


person Vlada Katlinskaya    schedule 29.12.2014    source источник
comment
Вы можете использовать ob_gzhandler(), чтобы позволить PHP сделать всю работу за вас, потому что функция gzuncompress() вернет ошибку, если несжатые данные превышают длину сжатых входных данных более чем в 32768 раз или превышают длину необязательного параметра. Или вы можете использовать необязательный параметр для определения длины. Это должно быть легко исправить.   -  person unixmiah    schedule 29.12.2014
comment
@unixmiah в моем случае размер файла составляет 4169 (сжатый) / 88406 (несжатый), поэтому соотношение далеко от 32768 (реальное соотношение составляет около 21).   -  person Vlada Katlinskaya    schedule 29.12.2014
comment
Вы редактировали php.ini и включали библиотеки zip? если вы этого не сделали, перезапустите веб-сервер после этого, чтобы применить сделанные вами изменения.   -  person unixmiah    schedule 29.12.2014
comment
@unixmiah Я включил скриншот phpinfo(), чтобы прояснить этот момент. Как я вижу - все включено. Верно?   -  person Vlada Katlinskaya    schedule 29.12.2014
comment
@VladaKatlinskaya: Посмотрите на ответ Марио.   -  person GiamPy    schedule 29.12.2014
comment
ааа вот в чем проблема, потоки неправильно помечены   -  person unixmiah    schedule 29.12.2014


Ответы (2)


Или вы можете просто использовать правильную функцию распаковки, gzdecode().

person mario    schedule 29.12.2014
comment
Проверено: работает! Большое спасибо! Вы знаете, почему функция gzuncompress() может вести себя таким образом? - person Vlada Katlinskaya; 29.12.2014
comment
@VladaKatlinskaya gzuncompress работает в так называемом формате zlib. В то время как gzdecode декодирует данные, упакованные в gzip. И gzinflate будет просто необработанными данными алгоритма DEFLATE. По сути, каждый из gzdecodegzuncompressgzinflate добавляет немного больше метаданных в потоки. - person mario; 29.12.2014
comment
Примечательно, что существует некоторая путаница из-за ранних ошибок MSIE/IIS, когда некоторые серверы отправляют потоки zlib, неправильно помеченные как данные gzip. Поэтому иногда вам придется проверять с помощью gzuncompress и gzdecode. Вот почему вы можете даже предпочесть использовать функции PHP curl, которые обрабатывают это автоматически. - person mario; 29.12.2014
comment
На самом деле эти ошибки приводили к тому, что необработанный deflate отправлялся в виде потоков zlib. Неправильно помеченных gzip-потоков не было. - person Mark Adler; 29.12.2014

Обратите внимание, что gzuncompress() может не распаковывать некоторые сжатые строки и возвращать ошибку данных.

Проблема может заключаться в том, что внешняя сжатая строка имеет контрольную сумму CRC32 в конце файла вместо Adler-32, как ожидает PHP.

(http://php.net/manual/en/function.gzuncompress.php#79042)

Это может быть вариант, почему он не работает.

Попробуйте с его кодом:

function gzuncompress_crc32($data) {
     $f = tempnam('/tmp', 'gz_fix');
     file_put_contents($f, "\x1f\x8b\x08\x00\x00\x00\x00\x00" . $data);
     return file_get_contents('compress.zlib://' . $f);
}

Измените свой код в этом:

error_reporting(E_ALL);
$f = file_get_contents('http://spiderbites.nytimes.com/sitemaps/www.nytimes.com/sitemap.xml.gz');
echo $f;
$f = gzuncompress_crc32($f);
echo "<hr>";
echo $f;

Насколько я проверил локально, это больше не дает ошибки.

person GiamPy    schedule 29.12.2014