PHP输出缓冲,ob_gzhandler引起的内容编码错误?

时间:2011-06-19 14:04:40

标签: php gzip output-buffering

任何人都可以解释为什么我收到以下错误?

在代码中,如果echo $gz;被注释掉,我没有收到任何错误(但也没有输出!),如果不是我得到的(来自Firefox),

  

内容编码错误

     
     

你的页面   试图查看无法显示   因为它使用无效或   不受支持的压缩形式。


感谢您的帮助,以下是代码:

ob_start('ob_gzhandler') OR ob_start();
echo 'eh?';
$gz = ob_get_clean();
echo $gz;

2 个答案:

答案 0 :(得分:15)

应用程序的输出应该只包含一个输出编码。如果您有多个编码方式不同的块,那么浏览器将得到一个无法使用的结果。因此编码错误。

Kohana本身已经使用了输出缓冲区。如果你想将它与你的ob_gzhandler输出缓冲区结合起来,你需要在kohana初始化它之前启动你的缓冲区。那是因为输出缓冲区是可堆叠的。当kohana完成输出缓冲后,你的申请将会适用:

ob_start('ob_gzhandler'); # your buffer:
   ob_starts and ends by kohana

因此,每当kohana完成一些输出时,这些块将被传递到输出回调(ob_gzhandler())并将进行gz编码。

浏览器应该只获取gz编码的数据,因为它是最顶层的输出缓冲区。

使用ob_gzhandler并手动回显缓冲区

如果您使用ob_start('ob_gzhandler')让PHP处理压缩然后echo ob_get_clean(),您将创建一个不可靠的输出。这与压缩与输出缓冲的工作方式有关:

PHP将缓冲输出块。这意味着,PHP开始压缩输出但保留一些字节以继续压缩。所以ob_get_clean()返回缓冲区的远程压缩部分。通常这个结果并不完整。

要解决这个问题,请先冲洗缓冲区:

ob_start('ob_gzhandler') OR ob_start();
echo 'eh?';
ob_flush();
$gz = ob_get_clean();
echo $gz;

确保之后没有更多输出。

如果你的PHP已经到了脚本的末尾,它就会照顾到:刷新和输出。

现在你需要手动调用ob_flush()来显式地让PHP通过回调推送缓冲区。

使用Curl检查HTTP压缩问题

由于firefox将返回错误,因此需要另一个工具来检查导致编码错误的原因。您可以使用curl来跟踪发生的情况:

curl --compress -i URL

在显示所有响应标头和未编码的主体时,将请求启用压缩的URL。这是必要的,因为PHP透明地启用/禁用基于请求标头的ob_gzhandler回调压缩。

响应还表明PHP也会设置所需的响应头。因此无需手动指定它们。这甚至是危险的,因为只有通过调用ob_start('ob_gzhandler'),你才能说压缩是否被启用。

如果压缩被破坏,curl将给出错误描述,但不会显示正文。

以下是由于错误的php脚本导致输出不完整而引发的卷曲错误消息:

HTTP/1.1 200 OK
X-Powered-By: PHP/5.3.6
Content-Encoding: gzip
...

curl: (23) Error while processing content unencoding: invalid code lengths set

通过添加--raw开关,您甚至可以进入原始响应正文:

curl --compress --raw -i URL

这可以给人留下什么样的错误,比如体内未压缩的部位。

答案 1 :(得分:0)

这是phpharo的作用:

/** output buffring */
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false)
{
 ob_start('ob_gzhandler'); ob_start();
}
else
{
 ob_start();
}