我将这个Perl脚本放在我的Apache服务器的cgi-bin文件夹中:
#!/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秒之后的整个输出。
有什么办法可以编写一个能够不断通知用户进度的脚本吗?我有一个脚本需要很长时间才能完成,我希望能够实时看到它的进度,而不是完整的脚本。
我还尝试将autoflush模式设置为off($ | = 0),但即便如此也没有。
答案 0 :(得分:5)
Randal Schwartz在Watching long processes through CGI中展示了更好的方法。
那就是说,说谎的内容类型无济于事。以下脚本完全按照您希望它在使用Apache 2.2的Windows XP上执行的操作(因为最后一行输出需要十秒钟):
#!/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,您无法避免这样的事实,即大多数浏览器都会等到他们认为已经足够开始呈现的页面。
答案 1 :(得分:4)
您希望实现的目标是什么 - 浏览器通常会渲染到目前为止收到的内容,即使它不是完整的文档,只要有足够的标记就可以呈现任何内容。我想知道为什么你使用\r\n
作为某些输出而只使用\n
作为其他输出 - 你应该保持一致并始终使用\n
。此外,您指定的是text / html的内容类型,但未在内容之前提供任何html标题(<html><title></title><body>
)。
但是,执行此操作的“现代”方法是立即返回页面输出,但稍后将要更新的部分保留为空<div>
元素。然后,您可以使用javascript(通过AJAX请求)更新该元素的内容。
答案 2 :(得分:2)
假设您使用的是比1.3更新的Apache版本,这应该可行。否则,你必须将你的脚本变成一个NPH(无解析标题)CGI,这意味着它的文件名应该以{{1}}为前缀,它应该输出完整的HTTP标题,例如。
nph-
请参阅(有点旧)Apache FAQ了解更多信息
答案 3 :(得分:2)
要查看您的脚本是否正常工作,请尝试使用命令行工具以避免与浏览器混淆。例如,curl
将在收到数据后立即输出。
如果您正在做的事情是出于重要目的,我不会使用您当前的方法。如果脚本需要很长时间才能运行,请将其分解到后台(info here)并使用进度更新文件或数据库。然后,您可以使用自动刷新(JavaScript或META-REFRESH)iFrame来显示进度。您也可以使用AJAX,但这需要更多参与。
答案 4 :(得分:0)
将内容类型设置为text / plain时,它是否符合您的期望?也许浏览器中的HTML解析会导致输出延迟,因为您实际上并没有输出有效的HTML? (没有&lt; html&gt;或&lt; body&gt;标签)
答案 5 :(得分:0)
通过禁用该特定虚拟主机的Deflate模块,它对我有用。
SetEnv no-gzip 1
我猜你也可以使用.htaccess文件获得相同的结果。