6

如何运行较长的 PHP 脚本并通过 HTTP 不断向浏览器发送更新?

与输出缓冲有关,但我不知道具体如何。

4

5 回答 5

3

输出缓冲的思考方向是正确的,在发送任何输出之前,您ob_start()可以像在脚本顶部的某个位置使用会话 ( ) 一样开始输出缓冲。session_start

然后,您可以使用ob_flushandflush来保持刷新输出。例如,如果您在一个foreach循环中并且在每个循环结束时您想要输出新行并等待 1 秒,您可以这样做。

但也要看看set_time_limit,因为否则人们可能会在 30 秒左右后遇到超时。

另一个快速说明,一些浏览器在实际开始显示之前需要最少的输出字节数。我不确定它是多少字节,我认为它在 4000 左右。此外,某些浏览器在关闭之前不会呈现某些元素(如表格)。所以冲洗在那里也不起作用。

于 2010-06-08T09:30:18.390 回答
2

这看起来像你所追求的:

输出缓冲,PHP 将脚本的输出在准备好后立即发送到您的 Web 服务器——这可能是逐行或逐个代码块的。

输出缓冲

ob_start() 函数用于创建一个新的输出缓冲区,您可以通过正常打印内容立即开始写入它。一旦你打开了一个缓冲区,有两种方法可以关闭它:ob_end_flush() 和 ob_end_clean(),这两种方法都会结束缓冲区,但方式略有不同。前者结束缓冲区并将所有数据发送到输出,后者结束缓冲区而不将其发送到输出,有效地清除了您保存在其中的任何信息。在输出缓冲区打开时输出的每一段文本都被放入该缓冲区,而不是发送到输出。考虑以下脚本:

<?php
  ob_start();
  print "In first buffer!\n";
  ob_end_flush();
  ob_start();
  print "In second buffer!\n";
  ob_end_clean();
  ob_start();
  print "In third buffer!\n";
?>

该脚本将输出“在第一个缓冲区中”,因为第一个文本被放入缓冲区,然后用 ob_end_flush() 刷新。但是,“在第二个缓冲区中”不会被打印出来,因为它被放置在一个使用 ob_end_clean() 清理的缓冲区中,而不是发送到输出。最后,脚本将打印出“在第三个缓冲区中”,因为 PHP 在到达脚本末尾时会自动刷新打开的输出缓冲区。

于 2010-06-08T09:27:53.527 回答
1

您还可以拥有一种后台任务,以及一个为您提供进度的界面。

例如,一个名为 job.php 的页面

<?php
    for ($i=0; $i<100; ++$i)
    {
       store($i);
       // long stuff
       sleep(42);
    }
?>

和progress.php

<?php
      return get($i);
?>

然后对progress.php?task=mytaskid 进行一些ajax 调用并更新GUI。我见过这种“大”文件上传的方法,发现它很棒。

编辑:抱歉,这并不能完全回答最初的问题。

于 2010-06-08T09:32:13.597 回答
1
<?php
# try this...
for (;;) {
  echo time() . '<br>';
  ob_flush(); # http://php.net/ob_flush
  flush(); # http://php.net/flush
  sleep(1); # http://php.net/sleep
}
?>
于 2010-06-08T09:38:56.073 回答
1

我使用简单的 HTTP 输出来更新页面,使其工作:

  • 确保关闭其中的所有打开元素<body>- 否则不会显示
  • 将输出的文本包含在一个元素中(例如 a <p>
  • 使用输出缓冲和正常刷新
  • 在 Firefox 3 上测试

这是我的代码:

for ($nc=0; $nc<10; $nc++){

    // delay just to test
    sleep(1);

    // send message to browser
    ob_end_clean();
    ob_start();
    echo "<p>Update ".$nc."</p>";
    ob_end_flush();
    flush();
}
于 2010-06-08T09:48:27.183 回答