我想知道为什么在使用gzcompress()之后我需要切掉最后4个字符。
这是我的代码:
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 -->
我只能在Chromes Code检查器中看到额外的N(不是在Firefox中,而是在IEs源中)。但是在代码的末尾会有四个附加字符。
任何人都可以解释一下,为什么我需要切断4个字符?
答案 0 :(得分:7)
gzcompress
实现了ZLIB compressed data format的<{3}}:
0 1
+---+---+
|CMF|FLG| (more-->)
+---+---+
(if FLG.FDICT set)
0 1 2 3
+---+---+---+---+
| DICTID | (more-->)
+---+---+---+---+
+=====================+---+---+---+---+
|...compressed data...| ADLER32 |
+=====================+---+---+---+---+
在这里您可以看到最后四个字节是following structure。
与此相反,Adler-32 checksum是所谓成员的列表,具有以下结构:
+---+---+---+---+---+---+---+---+---+---+
|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使用GZIP file format进行完整性检查。
所以要分析你的代码:
echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";
- 输出以下标题字段:
echo $index;
- 根据DEFLATE数据压缩格式输出压缩数据echo pack('V', $this->content_crc) . pack('V', $this->content_size);
- 以二进制形式输出CRC-32校验和和未压缩输入数据的大小答案 1 :(得分:2)
gzcompress产生这里描述的输出RFC1950,你正在切断的最后4个字节是adler32校验和。这是“deflate”编码,所以你应该设置“Content-Encoding:deflate”而不是操纵任何东西。
如果您想使用gzip,请使用gzencode()
,它使用gzip format。