Как работает gzcompress? - PullRequest
4 голосов
/ 08 июля 2010

Мне интересно, почему мне нужно обрезать последние 4 символа после использования gzcompress ().

Вот мой код:

header("Content-Encoding: gzip");
echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";
$index = $smarty->fetch("design/templates/main.htm") ."\n<!-- Compressed by gzip -->";
$this->content_size = strlen($index);
$this->content_crc = crc32($index);
$index = gzcompress($index, 9);
$index = substr($index, 0, strlen($index) - 4); // Why cut off ??
echo $index;
echo pack('V', $this->content_crc) . pack('V', $this->content_size);

Когда я не обрезаю последние 4 символа, источник заканчивается как:

[...]
<!-- Compressed by gzip -->N

Когда я их обрезаю, это звучит так:

[...]
<!-- Compressed by gzip -->

Я мог видеть дополнительный N только в инспекторе Chromes Code (не в Firefox и не в источнике IE). Но в конце кода должно быть четыре дополнительных символа.

Может кто-нибудь объяснить мне, почему я должен отрезать 4 символа?

Ответы [ 2 ]

7 голосов
/ 08 июля 2010

gzcompress реализует формат сжатых данных ZLIB , имеющий следующую структуру :

     0   1
   +---+---+
   |CMF|FLG|   (more-->)
   +---+---+

(if FLG.FDICT set)

     0   1   2   3
   +---+---+---+---+
   |     DICTID    |   (more-->)
   +---+---+---+---+

   +=====================+---+---+---+---+
   |...compressed data...|    ADLER32    |
   +=====================+---+---+---+---+

Здесь вы видите, чтопоследние четыре байта - это контрольная сумма Adler-32 .

В отличие от этого, формат файла GZIP представляет собой список так называемых элементов со следующей структурой:

   +---+---+---+---+---+---+---+---+---+---+
   |ID1|ID2|CM |FLG|     MTIME     |XFL|OS | (more-->)
   +---+---+---+---+---+---+---+---+---+---+

(if FLG.FEXTRA set)

   +---+---+=================================+
   | XLEN  |...XLEN bytes of "extra field"...| (more-->)
   +---+---+=================================+

(if FLG.FNAME set)

   +=========================================+
   |...original file name, zero-terminated...| (more-->)
   +=========================================+

(if FLG.FCOMMENT set)

   +===================================+
   |...file comment, zero-terminated...| (more-->)
   +===================================+

(if FLG.FHCRC set)

   +---+---+
   | CRC16 |
   +---+---+

   +=======================+
   |...compressed blocks...| (more-->)
   +=======================+

     0   1   2   3   4   5   6   7
   +---+---+---+---+---+---+---+---+
   |     CRC32     |     ISIZE     |
   +---+---+---+---+---+---+---+---+

Как видите, GZIP использует контрольную сумму CRC-32 для проверки целостности.

Итак, для анализа вашего кода:

  • echo "\x1f\x8b\x08\x00\x00\x00\x00\x00"; - выводит следующие поля заголовка:
    • 0x1f 0x8b - ID1 и ID2, идентификаторы для определения формата данных (это фиксированные значения)
    • 0x08 - CM, сжатиеметод, который используется;8 обозначает использование формата сжатия данных DEFLATE (RFC 1951)
    • 0x00 - FLG, флаги
    • 0x00000000 - MTIME, время модификации
    • поля XFL (дополнительные флаги) и OS (операционная система) задаются форматом сжатия данных DEFLATE
  • echo $index; - выводит сжатые данные в соответствии с форматом сжатия данных DEFLATE
  • echo pack('V', $this->content_crc) . pack('V', $this->content_size); - выводит контрольную сумму CRC-32 и размер несжатых входных данных в двоичном виде
2 голосов
/ 08 июля 2010

gzcompress производит вывод, описанный здесь RFC1950 , последние 4 байта, которые вы отсекаете, это контрольная сумма adler32.Это кодировка «deflate», поэтому вы должны просто установить «Content-Encoding: deflate» и ничего не манипулировать.

Если вы хотите использовать gzip, используйте gzencode(), который использует gzipформат .

...