2009-10-29 30 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文件實現相同的結果。