【问题标题】:PHP Output buffering, Content Encoding Error caused by ob_gzhandler?PHP输出缓冲,ob_gzhandler引起的内容编码错误?
【发布时间】:2011-09-18 04:05:18
【问题描述】:

谁能解释为什么我收到以下错误?

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

内容编码错误


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


感谢您的帮助,代码如下:

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

【问题讨论】:

  • 您是否设置了适当的 Content-Encoding 标头? “嗯?”顺便说一句,这里没有压缩。
  • @Kemo 我没有手动设置 Content-Encoding 标头,不,但 Firebug 显示它无论如何设置正确,我现在也尝试手动设置它,但没有区别。我知道"eh?" 在我的示例中没有被压缩 - 正如我在问题中提到的那样,我只是用它来表明无论我是否返回压缩的内容都会发生错误。我想我会更清楚一点。谢谢。

标签: php gzip output-buffering


【解决方案1】:

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

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 将给出错误描述但不会显​​示正文。

以下是这样的 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

这可以让人知道出了什么问题,比如身体内未压缩的部分。

【讨论】:

  • 糟糕,抱歉 - 在您输入答案时,我完全重写了问题。如果您的答案解决了原始问题,我将回滚,但正如您在更新后的问题中看到的那样 - 我可能过于仓促地认为这是一个 Kohana 问题,即使我没有通过路由,我也会遇到同样的错误小花。不过感谢您的回复 - 我会好好读一读……现在。
  • 好的,谢谢。用curl 尝试过,似乎响应是通过未编码的,但是用Content-Encoding: gzip 因此解码时出错。
  • 测试我添加的代码示例。有用。用 curl 和 firefox 追踪到这个。
  • 太棒了。非常感谢。
  • 是的,对我来说也是新手,有很多细节。让我知道这是否也用 Kohana 解决了。
【解决方案2】:

这就是 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();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    相关资源
    最近更新 更多