mod_gzip是一个Apache模块,其功能是使用Gzip压缩静态的html页面,遵循IETF标准的浏览器可以接受gzip编码(IE, Netscape等)。mod_gzip可以将页面的下载时间提高4-5倍。我强烈建议你在你的web服务器上使用mod_gzip。然而,我们还必须用PHP建立我们自己的压缩引擎。在这篇文章里,我将要介绍如何使用PHP的输出控制函数来大幅加速页面载入速度。
介绍PHP的输出控制函数
PHP4中最令人满意的事是——你可以让PHP缓存所有由脚本生成的输出,在你决定把它们送出之前,浏览器方是不会收到任何内容的。在脚本程序中你能用这些函数来设置header、cookies,然而这只是强大的输出函数的一小部分功能。
复制代码 代码如下:
<?php
void ob_start(void);
?>
告诉PHP处理器把所有的输出重定向到一个内部的缓存(buffer)中。在调用ob_start之前,没有输出会被送到浏览器去。
复制代码 代码如下:
<?php
string ob_get_contents(void);
?>
该函数将“输出缓存”(output buffer)以字符串的形式返回。你可以调用该函数把积累下来的输出送到浏览器中。(仅在把buffering功能关闭之后!!)
复制代码 代码如下:
<?php
int ob_get_length(void);
?>
返回缓存中的字符串的长度。
复制代码 代码如下:
<?php
void ob_end_clean(void);
?>
清空输出缓存,并将输出缓存关闭。在缓存中的内容输出到浏览器之前,必须使用这个函数。
void 501([int flag])
用来打开/关闭隐含的flush动作开关(默认是关)。如果flush是开的,每次调用print/echo或是其它输出命令的时候,输出的内容会被立即送到浏览器端。
使用输出控制来压缩PHP输出
你必须使用PHP4里编译的Zlib扩展包来压缩输出。如果需要的话,可以查看PHP文档中有关Zlib包的安装指导。
首先,初始化输出缓存:
复制代码 代码如下:
<?php
ob_start();
ob_implicit_flush(0);
?>
之后,用print, echo, 或其他你喜欢的方法生成所有输出内容,例如:
复制代码 代码如下:
<?php
print("Hey this is a compressed output!");
?>
页面生成后,我们取回输出内容:
复制代码 代码如下:
<?php
$contents = ob_get_contents();
ob_end_clean();
?>
之后,必须检测浏览器是否支持压缩数据。如果支持,浏览器会发给服务器端一个ACCEPT-ENCODEING HTTP头。我们只需检查$HTTP_ACCEPT_ENCODING变量中是否有“gzip,deflate”字串。
复制代码 代码如下:
<?php
if(ereg('gzip, deflate',$HTTP_ACCEPT_ENCODING)) {
// 在这里生成 Gzip 压缩的内容
} else {
echo $contents;
}
?>
这种方法使用起来既简单又结构清晰。下面让我们看看如何生成压缩的输出:
复制代码 代码如下:
<?php
//告诉浏览器将要收到的是gzip数据
//当然在此之前,你已经检查了它们是否支持gzip,x-gzip数据格式
//如果支持的是x-gzip,那么下面的头就要用z-gzip来代替
header("Content-Encoding: gzip");
//显示gzip文件的头
//只需显示一次
echo "x1fx8bx08x00x00x00x00x00";
//计算出文件的大小和CRC码
$Size = strlen($contents);
$Crc = crc32($contents);
//压缩数据
$contents = gzcompress($contents, 9);
//我们不能就这样输出,因为CRC码是混乱的。
//如果我在这里使用“echo $contents”,压缩的数据会被送出,
//但是却不完整。文件最后的四个字节是CRC校验码,可是只发出去了三个字节。
//最后一个字节被丢掉了。我不知道这个bug在4.0.2版中解决了没有,
//不过最好避免错误的方法是把正确的CRC校验码加到压缩的数据的末尾。
//
//把旧的CRC校验码剥离
$contents = substr($contents, 0, strlen($contents) - 4);
//仅显示压缩的数据
echo $contents;
//输出CRC,和原来数据的大小(字节)
gzip_PrintFourChars($Crc);
gzip_PrintFourChars($Size);
function gzip_PrintFourChars($Val) {
for ($i = 0; $i <4; $i ++) {
echo chr($Val % 256);
$Val = floor($Val / 256);
}
}
?>
//好了,你还可以按此方式附加上更多的压缩数据。
要想进行实际的测试,所有的脚本代码如下:
复制代码 代码如下:
<?php
ob_start();
ob_implicit_flush(0);
print("I'm compressed!n");
$contents = ob_get_contents();
ob_end_clean();
header("Content-Encoding: gzip");
echo "x1fx8bx08x00x00x00x00x00";
$Size = strlen($contents);
$Crc = crc32($contents);
$contents = gzcompress($contents, 9);
$contents = substr($contents, 0, strlen($contents) - 4);
echo $contents;
gzip_PrintFourChars($Crc);
gzip_PrintFourChars($Size);
function gzip_PrintFourChars($Val) {
for ($i = 0; $i <4; $i ++) {
echo chr($Val % 256);
$Val = floor($Val / 256);
}
}
?>
缓存PHP输出