2009-10-29 87 views
5

我有这样的Perl脚本坐在我的Apache服务器的CGI-bin文件夹:如何从Perl CGI脚本持续告知用户进度?

#!/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),但即使没有做任何事情。

+0

您使用的是哪个版本的Apache?比1.3还新? – Hasturkun 2009-10-29 17:47:37

回答

5

兰德尔·施瓦茨表示Watching long processes through CGI一种更好的方式。

这就是说,说谎的内容类型将无济于事。下面的脚本不正是你似乎什么希望它在Windows XP上使用Apache 2.2(因为它需要十秒输出的最后一行出现)做:现在

#!/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 ,你无法避免大多数浏览器会等到他们认为足够的页面才能开始呈现的事实。

4

你是想达到什么是可能的 - 浏览器一般呈现它至今已收到,即使是不完整的文档,只要有足够的标记,以便能够使任何东西。不过,我想知道为什么你使用\r\n作为输出,而其他输出使用\n,你应该始终如一地使用\n。此外,您正在指定文本/ html的内容类型,但不会在您的内容之前提供任何html标题(<html><title></title><body>)。

但是,“现代”方法是立即返回页面输出,但稍后将要更新的部分保留为空的<div>元素。然后你可以用javascript(通过AJAX请求)更新该元素的内容。

+0

尝试输出一个有效的HTML页面,仍然是相同的响应... – Jibran 2009-10-29 17:56:45

0

当您将内容类型设置为文本/纯文本时,它会执行您期望的操作吗?也许浏览器中的HTML解析会导致输出延迟,因为你实际上并没有输出有效的HTML? (否<html>或<body> tags)

+0

尝试将输出类型设置为文本/纯文本,仍然没有...输出仍然延迟。 – Jibran 2009-10-29 17:56:12

+0

你使用什么浏览器?如果浏览器执行内容嗅探,那么如果您发送html,它将简单地忽略您的内容类型。 – innaM 2009-10-29 20:07:53

2

假设您使用的是比1.3更新版本的Apache,这应该可以工作。否则,您必须将您的脚本变为NPH(无解析标题)CGI,这意味着它的文件名应以nph-为前缀,并且它应输出完整的HTTP标头,例如。

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

看到了(有点老)Apache FAQ更多信息

2

要查看您的脚本工作,请尝试使用命令行工具,以避免与您的浏览器的任何混淆。例如,curl会在收到数据后立即输出。

如果你在做什么是一个重要的目的,我不会用你目前的做法,虽然。如果脚本需要很长时间才能运行,请将其分离到后台(info here),然后使用进度更新文件或数据库。然后,您可以使用自动刷新(JavaScript或META-REFRESH)iFrame来显示进度。你也可以使用AJAX,但是这涉及更多一点。

0

它为我工作通过禁用该特定虚拟主机的Deflate模块。

SetEnv no-gzip 1 

我想你也可以使用.htaccess文件实现相同的结果。