【问题标题】:PHP Error: ob_flush() [ref.outcontrol]: failed to flush buffer. No buffer to flushPHP 错误:ob_flush() [ref.outcontrol]:刷新缓冲区失败。没有要刷新的缓冲区
【发布时间】:2012-02-29 05:24:47
【问题描述】:

有人可以保存这 2 个文件并运行它们并告诉我为什么会收到错误“ob_flush() [ref.outcontrol]: failed to flush buffer. No buffer to flush”。我试着用谷歌搜索,它说我必须使用 ob_start();但是当我这样做时,它不会逐行打印出来,而是在完成后从 FOR 循环中返回整个对象。我对 PHP 有点陌生,所以我不知道还能去哪里找。。

test_process.php

// This script will write numbers from 1 to 100 into file
// And sends continuously info to user
$fp = fopen( '/tmp/output.txt', 'w') or die('Failed to open');
set_time_limit( 120);
ignore_user_abort(true);

for( $i = 0; $i < 100; $i++){
    echo "<script type=\"text/javascript\">parent.document.getElementById( 'foo').innerHTML += 'Line $i<br />';</script>";
    echo str_repeat( ' ', 2048);
    flush();
    ob_flush();
    sleep(1);
    fwrite( $fp, "$i\n");
}

fclose( $fp);

ma​​in.html

<html>
    <head>
        <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript" charset="utf-8"></script>

        <style type="text/css" media="screen">
            .msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
            .new{ background-color:#3B9957;}
            .error{ background-color:#992E36;}
        </style>

    </head>
    <body>

        <iframe id="loadarea" width="1024px" height="768px"></iframe><br />
        <script>
            function helper() {
                document.getElementById('loadarea').src = 'test_process.php';
            }
            function kill() {
                document.getElementById('loadarea').src = '';
            }
        </script>

        <input type="button" onclick="helper()" value="Start">
        <input type="button" onclick="kill()" value="Stop">
        <div id="foo"></div>


</body>
</html>

【问题讨论】:

  • 检查你在php.ini中关于输出缓冲区的配置,它可以自动启用on_start。检查它是否启用的另一种方法是在开始时使用 ob_end_flush() 并删除所有刷新。您也可以通过phpinfo(); 进行检查
  • 您好,感谢您的回复。我尝试启用输出缓冲,但随后它返回整个 for 循环对象而不是逐行...

标签: php ajax while-loop flush


【解决方案1】:

需要ob_flush(),如果输出缓冲区处于活动状态(例如通过ob_start(),或通过配置设置)。如果还没有,只需删除 ob_flush()。或者你可以让它有条件:

 if (ob_get_level() > 0) {ob_flush();}

【讨论】:

  • 您好,感谢您的回复。我试图取出 ob_flush() 但它仍然只在完成处理后才返回整个 for 循环对象,而不是逐行返回。
  • 请记住,在显示之前缓存可能发生在您和 UA 之间的任何地方:在 PHP 中,在网络服务器中,在网络上的任何代理或跃点中,在您的本地网络上,在您的本地计算机,在本地浏览器中。最多,您可以提示(如果没有活动的输出缓冲区ob_flush 对您没有任何好处),如果您需要,您不应该使用 HTTP,而是使用其他直接套接字连接.
  • 但由于某种原因,当 ob_flush() 存在时它可以工作,但它也会抛出该错误,因此如果该错误消失就完美了哈哈
  • 仅在错误显示时,还是在display_errors 关闭时?因为如果它是第一个,它很可能只是在其他地方触发刷新的非空内容的数量。
  • 当我关闭 display_errors 然后它再次返回整个对象
【解决方案2】:

我认为您将ob_flush()flush() 混淆了。虽然ob_start()ob_flush() 处理捕获所有输出的PHP 内部输出缓冲区,但flush() 是刷新STDOUT 的普通函数,就像在其他编程语言中一样。

例子:

<?php
ob_start();
echo "Foobar\nFoobar\nFoobar\n";
// Nothing printed yet
ob_flush(); // Now it is printed.

echo "Foobar\n"; // Printed directly, because contains a line ending.

echo "Foobar"; // Not printed, because normally buffers are flushed on line endings
flush();  // Printed.

编辑:

不会打印您的输出,因为您的网络服务器可能会缓冲内容。尝试关闭压缩和输出缓冲:

@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);

还请记住,Safari 和 Internet Explorer 有一个内部 1K 缓冲区。因此,您需要添加 1 KB 的填充数据(如空格),以使它们呈现。

编辑 2: 你的实现被破坏了。您想使用 ajax 轮询您的数据。在客户端使用 jQuery:

<div id="counter">0%</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
<script type="text/javascript">
function doPoll(){
    $.post('script-that-returns-stuff.php', function(data) {
        $("#counter").html(data);
        setTimeout(doPoll,5000);
    });
}
doPoll();
</script>

然后在script-that-returns-stuff.php:

<?php
$file = explode("\n", file_get_contents("/tmp/output.txt"));
$last_line = $file[count($file)-1];
echo $last_line."%";

【讨论】:

  • 您好 - 感谢您的回复。我尝试了您的建议,但由于某种原因,它不会逐行返回,而是仅在完成处理后才返回整个 for 循环结果。
  • 然后以干净的方式实现它。创建一个每秒轮询服务器的 JavaScript 和一个 PHP 脚本,它返回文件中的行数。然后在客户端显示。
  • 好的,请参阅编辑 2 了解 AJAX 实现。它每 5 秒轮询一次。要更频繁地进行投票,只需减少setTimeout中的数字
  • 嘿,我试过了,但是用 while 或 for 循环它不会刷新,它只是返回循环的处理结果,而不是每次循环时的结果
  • 1K 缓冲区是我在 PHP 中实现 EventSource 循环的一个神秘问题。我可以通过在循环开头添加echo str_repeat(" ", 1024), "\n"; 来克服它,突然之间,一切正常!
【解决方案3】:

ob_start() 在哪里?

ob_flush 将输出缓冲区刷新到您的文件句柄。也许你错了。

一个例子:

ob_start(); //start output buffering
echo 'hello world'; //not outputed
ob_flush(); //sends the output buffer so displays hello world.

manual

【讨论】:

  • 您好,感谢您的回复。我没有将它包含在上面的代码中,因为当我这样做时,它不会逐行返回,而是仅在完成处理后才返回整个 for 循环结果。
猜你喜欢
  • 1970-01-01
  • 2018-07-11
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
  • 1970-01-01
  • 2011-11-28
  • 1970-01-01
相关资源
最近更新 更多