【问题标题】:PHP Output complete notificationPHP 输出完成通知
【发布时间】:2009-11-08 11:24:56
【问题描述】:

我正在尝试找到一种方法让 PHP 向浏览器指示所有页面输出已完成。页面完成后,我们正在运行一些通常不会花费很长时间的统计代码,但万一发生了,我不希望用户浏览器等待更多数据。这不能通过 JavaScript 完成,因为它需要在手机上工作。

我已经开始使用输出缓冲

mb_http_output("UTF8"); 
ob_start("mb_output_handler");

以确保我的网站 MB 文本(日语)没有问题。我希望 ob_end_flush() 能解决问题,但如果我放置 sleep(10);在 ob_end_flush() 之后,浏览器再等待 10 秒。有人对此有任何想法吗?

更新: 使用下面我“ob_gzhandler”的jitters方法让它与gzip一起工作有人在这里看到任何可能的问题吗?

//may be also add headers for cache-control and expires (IE)
header("Connection: close"); //tells browser that connection will be closed
ob_start();
ob_start("ob_gzhandler");
//page content
ob_end_flush();
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();

再次更新:

请再看看上面的代码。你需要做一个 ob_start();在 ob_start("ob_gzhandler"); 之前然后调用 ob_end_flush();在调用 ob_get_length() 之前,您可以获得正确的 gzip 压缩大小。

【问题讨论】:

    标签: php


    【解决方案1】:

    按照这些思路使用一些东西

    //may be also add headers for cache-control and expires (IE)
    header("Connection: close"); //tells browser that connection will be closed
    ob_start();
    //generate your output
    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush();
    flush();
    //continue statistic processing
    

    【讨论】:

    • 我试过这个,如果我添加类似 sleep(20);在flush()之后;浏览器 (FireFox 3.5) 仍会再显示 20 秒的加载指示器。
    • 我终于得到了这个工作,但前提是我包含 header("Content-Encoding: none");标题正下方(“连接:关闭”);关于为什么会这样的任何想法?
    • 关于如何通过设置 header("Content-Encoding: none");我宁愿尽可能让 gzip 继续运行
    • 将 encoding 设置为 none 可能会阻止(例如)apache 使用具有自己的缓冲区的 mod_gzip,因此可能会阻止上述脚本工作。要使我的脚本正常工作,您可能必须为此脚本禁用 gzip 和/或禁用 apache 输出缓冲。
    • 我找到了一种使用 gzip 的方法。我用更改更新了我的原始帖子,所以代码会很好看。
    【解决方案2】:

    我认为没有办法通知浏览器输出已完成,至少从发送输出的脚本中是这样。如果您使用其他脚本来监视您的第一个脚本的输出并使用 iframe,那么您也许可以做到。

    当页面被认为已加载时,浏览器知道输出何时完成。这是浏览器知道的。

    【讨论】:

      【解决方案3】:

      您可以在后台创建一个新的 php 进程并让它处理统计数据。就像是: shell_exec('php stats.php &');

      末尾的 & 确保它在后台运行,因此即使 stats.php 需要 20 秒,访问者也不会注意到它。 您可能需要将数据传递给 stats 脚本,您可以通过传入参数来完成,如下所示:

      shell_exec('php stats.php -b '. escapeshellarg($_SERVER['HTTP_USER_AGENT']) .' &');

      在 stats.php 中,您将使用 $argv 变量来获取该数据。

      但如果统计代码运行时间不长,我不会这样做,因为像这样为每个页面加载分叉一个新进程会产生一些开销。我不知道是什么让统计代码需要很长时间才能处理,但另一种解决方案可能是将原始数据插入数据库,并让后台作业处理该数据以创建可用的统计数据。这可以通过 cron 作业或在处理队列的无限循环中运行屏幕来完成。

      【讨论】:

      • 在 PHP 中,如果您希望新进程在后台运行,您还必须重定向 stdout,例如shell_exec('php stats.php > /dev/null &');
      • 没错,忘记了。也可以将 stderr 指向 stdout,然后将 stdout 指向 /dev/null。
      【解决方案4】:

      尝试将您的统计代码移动到一个单独的函数中,并在渲染页面上的 javascript 代码中的 dom.ready 或 onload 事件中使用 ajax 调用来调用此函数,就像在此元代码中一样:

      <html>
        <script type="text/javascript">
          dom.onready = Ajax.call(location.href + '?do_stats');
        </script>
        <body>...
      </html>
      

      dom.ready 事件可以由 jQuery 或 Prototype 库提供。缺点是它只能在启用 js 的情况下工作。

      或者,您可以将所有需要的统计信息记录到数据库中,然后发送一个脚本,从那里收集排队的数据并在后台处理它 - 例如使用 cron。

      【讨论】:

      • 很遗憾,大多数日本手机不支持 javascript,尤其是在日本,它们通常可以占您总用户群的 50% 或更多。
      • 好的,您的问题中缺少重要的一点。你应该修改它。
      • 我确实忘记提及了。对不起。
      猜你喜欢
      • 2015-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-17
      • 2015-02-13
      • 1970-01-01
      相关资源
      最近更新 更多