输出压缩问题


Output Compression problems

我在尝试使用 php 输出压缩时遇到问题,我已经搜索了很多小时,但我仍然没有任何线索......

让我们看一个简单的脚本:

<?php 
$response = "abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh";
if(function_exists('ob_gzhandler')) 
{
  ob_start('ob_gzhandler');
}
else {
  ob_start();
}

echo $response;
ob_end_flush();

这是我在互联网上找到的一种方法,它曾经对我有用......但不再(我不知道为什么)。

如果我在调用此脚本时查看 http 标头:

请求:

Host: 192.168.51.191
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cache-Control: max-age=0

响应:

Connection: Keep-Alive
Content-Type: text/html
Date: Tue, 26 Jan 2016 15:19:07 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.9 (Win64) OpenSSL/1.0.1g PHP/5.5.12
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: PHP/5.5.12

你可以看到响应没有压缩(Firebird 给了我一个 0.06ko 的响应),服务器使用分块编码发送响应。

我尝试了另一种方法来发送压缩响应:

<?php 
    $response = "abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh"; 
    $replyBody = gzencode($response, 9, FORCE_GZIP);
    header("Content-Encoding: gzip");
    echo $replyBody;
响应标头如下

(请求标头始终相同):

响应:

Connection: Keep-Alive
Content-Type: text/html
Date: Tue, 26 Jan 2016 15:29:01 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.9 (Win64) OpenSSL/1.0.1g PHP/5.5.12
Transfer-Encoding: chunked
X-Powered-By: PHP/5.5.12

如您所见,这与第一种方法中的行为基本相同。

然后如果我尝试这个:

<?php 
$response = "abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh";
$replyBody = gzencode($response, 9, FORCE_GZIP);
echo $replyBody;

我收到看起来像压缩响应(随机字符)的东西,输出大小为 0.03ko.

这里对应响应 http 标头:

Connection: Keep-Alive
Content-Length: 31
Content-Type: text/html
Date: Tue, 26 Jan 2016 15:32:46 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.9 (Win64) OpenSSL/1.0.1g PHP/5.5.12
X-Powered-By: PHP/5.5.12

它让我认为压缩部分工作正常,因为输出大小已减小(它显然不可读,因为浏览器无法知道它是压缩内容)。

这就是我迷路的地方...

如果我理解正确,当我手动发送压缩数据(使用 gzencode)时,如果我设置标题"内容编码:gzip",网络服务器/php 似乎在将其发送到浏览器之前将其解压缩???怎么可能?

为什么它将其作为"分块"数据发送而不是设置内容长度标头?

我尝试在响应中手动设置内容长度; 它不会改变任何东西(它不会出现在响应标头中,我仍然会有一个"分块"响应。

我在某处看到我必须在发送其他数据或标头之前编写"Content-Length"标头以避免"分块"响应,我尝试过并且仍然有相同的结果。

我认为这可能是我的 php 测试脚本开头的 BOM 字符的问题,但它在没有 BOM 编码的情况下以 UTF-8 保存,所以我认为这不是问题所在。

我在我的开发计算机(使用 wampserver)和生产环境 (IIS) 上遇到了这个问题,以前它在两台服务器上工作。

我在使用多个浏览器时遇到了这个问题,我检查了我之前用小提琴手写的响应大小。

有没有人看到问题可能在哪里?

提前致谢

如果我是你,我会通过以下清单。

1. 检查是否已安装zlib扩展。

ob_gzhandler需要zlib扩展才能工作。没有它,它只是静默地回退到默认设置。

2. 验证您的php.ini是否未启用zlib.output_compression

如此处所述,即使zlib.output_compression优先于ob_gzhandler(),您也不能同时使用两者。所以你的代码变成了..

if (extension_loaded('zlib') && !ini_get('zlib.output_compression')){
    ob_start('ob_gzhandler');
} 

3.检查标头是否已发送,例如,在 ob_start(ob_gzhandler) 这将防止压缩输出被检测为这样。例如。在代码中的某个位置<?phpecho之前具有某些字符。

4. 确保除了 apache( mod_deflate 中的 gzip 之外,您没有使用上述所有内容。这只会导致输出被双重压缩,这很可能会混淆浏览器。