Apache/Linux 上的 PHP 输出缓冲区刷新问题

Apache/Linux 上的 PHP 输出缓冲区刷新问题

我在 Linux Web 服务器上遇到了 PHP 输出缓冲区刷新问题。在我的代码中,输出缓冲区维护正确,所有正确的数据都推送到其中,但通常的刷新机制不会将其刷新到浏览器。我尝试了这里发布的所有方法:http://php.net/manual/en/function.flush.php但目前还没有成功。

我从 php.net 获取了一个小脚本来测试它:

<?php
    ob_start();
    for($i=0;$i<70;$i++)
    {
        echo 'printing...<br />';
        ob_get_flush();
        flush();
        usleep(300000);
    }
?>

这应该会向浏览器打印 70 次“printing...”,每三秒一行。这在我的其他基于 Windows 的测试环境中运行良好(仍然使用 apache、XAMPP 包),但在我的 Linux 服务器上却不行。它等待脚本完成,然后再向浏览器提供任何内容,基本上忽略了整个刷新命令。

如果有人曾经遇到过这种情况或者知道任何可以提供帮助的信息(无论是服务器配置还是代码调整),我们将不胜感激!

答案1

我遇到了这个问题,发现了以下几行:

while ( @ob_end_flush() ); // even if there is no nested output buffer
flush();

就能解决问题。

结果可能有所不同。这在我的 IE 和 Apache 2.0.55 系统上有效。

杰夫

答案2

刷新 PHP 的输出缓冲区和刷新 Apache 的缓冲区是两个不同的任务。经常发生的情况是,您刷新了 PHP 的输出缓冲区,但 Apache 不会向浏览器发送任何内容,直到有更多数据为止。此外,有时浏览器在收到足够的数据之前不会显示任何内容。您可以尝试用换行符“填充”输出。

您发布的代码还有另外两个问题。首先,它启动一次输出缓冲,然后在循环中多次结束它。您要么希望在循环内部也启用输出缓冲,要么可能只是省略它。另一个问题是,它将以ob_get_flush()字符串形式返回输出缓冲区的内容,而不是回显它。

尝试一下这个代码:

<?php
    for($i=0;$i<70;$i++)
    {
        echo 'printing...<br />';
        echo str_repeat("\n",1024);
        flush();
        usleep(300000);
    }
?>

来自 PHP 手册:

flush() 可能无法覆盖你的 web 服务器的缓冲方案,并且它对浏览器中任何客户端缓冲都没有影响。 [...]

Apache 的服务器模块(例如 mod_gzip)可能会进行自己的缓冲,这将导致 flush() 不会立即将数据发送到客户端。

浏览器甚至可能在显示输入之前对其进行缓冲。例如,Netscape 会缓冲文本,直到收到行尾或标签开头为止,并且直到看到最外层表格的标签时才会呈现表格。

某些版本的 Microsoft Internet Explorer 仅在收到 256 字节的输出后才会开始显示页面,因此您可能需要在刷新之前发送额外的空格以使这些浏览器显示页面。

我的示例尝试通过发送 1024 个换行符来解决这个问题。

答案3

正如 PHP 文档中所述,根据我的经验,造成这种情况的一个常见原因是 Apache 上的 mod_gzip 的输出缓冲。现在许多发行版都默认启用了此功能。

标记

相关内容