【问题标题】:How can I continuously inform the user of progress from a Perl CGI script?如何不断地通知用户 Perl CGI 脚本的进度?
【发布时间】:2010-12-11 08:17:59
【问题描述】:

我的 Apache 服务器的 cgi-bin 文件夹中有这个 Perl 脚本:

#!/usr/bin/perl 
use strict;
use warnings;

$| = 1;

print "Content-type: text/html\r\n\r\n";
print "Hello there!<br />\nJust testing .<br />\n";

my $top = 5;
foreach (1..$top) {
    print "i = $_<br />\n";
    sleep 1;
}

我想在这里实现的是网页的逐步更新,以向用户显示更新的状态。但是,我实际上得到的是在 5 秒延迟后立即获得整个输出。

有什么方法可以编写一个能够不断通知用户其进度的脚本?我有一个脚本需要很长时间才能完成,我希望能够实时看到它的进度,而不是完成整个脚本。

我也尝试将自动刷新模式设置为关闭 ($| = 0),但即使这样也无济于事。

【问题讨论】:

  • 您使用的是哪个版本的 Apache?比 1.3 更新?

标签: perl apache cgi


【解决方案1】:

Randal Schwartz 在Watching long processes through CGI 中展示了一种更好的方法。

也就是说,对内容类型撒谎也无济于事。以下脚本正是您希望它在带有 Apache 2.2 的 Windows XP 上执行的操作(因为显示最后一行输出需要 10 秒钟):

#!/usr/bin/perl

use strict;
use warnings;

use CGI qw(:cgi);

print header('text/plain');

$| = 1;

print "Job started\n";

for ( 1 .. 10 ) {
    print "$_\n";
    sleep 1;
}

现在,如果您要发送 HTML,则无法避免这样一个事实,即大多数浏览器会等到他们认为足够的页面才开始呈现。

【讨论】:

    【解决方案2】:

    您想要实现的目标是可能的——浏览器通常会呈现它迄今为止收到的内容,即使它不是完整的文档,只要有足够的标记能够呈现任何东西。但是我想知道为什么您将\r\n 用于某些输出而仅将\n 用于其他输出——您应该始终保持一致并始终使用\n。此外,您指定了 text/html 的内容类型,但没有在您的内容之前提供任何 html 标头 (&lt;html&gt;&lt;title&gt;&lt;/title&gt;&lt;body&gt;)。

    但是,执行此操作的“现代”方式是立即返回页面输出,但将稍后要更新的部分保留为空的 &lt;div&gt; 元素。然后,您可以使用 javascript(通过 AJAX 请求)更新该元素的内容。

    【讨论】:

      【解决方案3】:

      假设您使用的 Apache 版本高于 1.3,这应该可以工作。否则,你必须将你的脚本变成一个 NPH(No Parsed Headers)CGI,这意味着它的文件名应该以 nph- 为前缀,并且它应该输出完整的 HTTP 头,例如。

      HTTP/1.1 200 OK\n
      Content-type: text/html\n\n
      

      查看(有些旧的)Apache FAQ 了解更多信息

      【讨论】:

        【解决方案4】:

        要查看您的脚本是否正常工作,请尝试使用命令行工具以避免与浏览器混淆。比如curl,一收到数据就会输出。

        如果您正在做的事情是出于重要目的,那么我不会使用您当前的方法。如果脚本需要很长时间才能运行,请将其分叉到后台 (info here) 并根据进度更新文件或数据库。然后,您可以使用自动刷新(JavaScript 或 META-REFRESH)iFrame 来显示进度。您也可以使用 AJAX,但这有点复杂。

        【讨论】:

          【解决方案5】:

          当您将内容类型设置为 text/plain 时,它是否符合您的预期?也许您的浏览器中的 HTML 解析导致输出延迟,因为您实际上并没有输出有效的 HTML? (没有 或

          标签)

          【讨论】:

          • 尝试将输出类型设置为 text/plain,仍然没有...输出仍然延迟。
          • 你用的是什么浏览器?如果浏览器进行内容嗅探,如果您仍然发送 html,它将简单地忽略您的内容类型。
          【解决方案6】:

          它通过禁用特定虚拟主机的 Deflate 模块对我有用。

          SetEnv no-gzip 1
          

          我猜你也可以使用 .htaccess 文件获得相同的结果。

          【讨论】:

            猜你喜欢
            • 2012-03-10
            • 1970-01-01
            • 1970-01-01
            • 2010-11-29
            • 1970-01-01
            • 2012-10-15
            • 2012-05-31
            • 2013-05-13
            相关资源
            最近更新 更多