2009-10-29 2 views
5

Ich habe diesen Perl-Skript im Ordner cgi-ist von meinem Apache-Server sitzt:Wie kann ich den Benutzer fortlaufend über ein Perl-CGI-Skript informieren?

#!/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; 
} 

Was will ich hier eine allmähliche Aktualisierung der Web-Seite erreichen, um den Benutzer einen aktualisierten Status zu zeigen. Was ich jedoch tatsächlich bekomme, ist die gesamte Ausgabe auf einmal, nach einer Verzögerung von 5 Sekunden.

Gibt es eine Möglichkeit, ein Skript zu schreiben, das den Benutzer kontinuierlich über seinen Fortschritt informiert? Ich habe ein Skript, das sehr lange braucht, bis ich fertig bin und ich möchte seinen Fortschritt in Echtzeit sehen, anstatt das ganze Skript zu beenden.

Ich habe auch versucht, Autoflush-Modus zu deaktivieren ($ | = 0), aber selbst das tut nichts.

+0

In welcher Version von Apache befinden Sie sich? neuer als 1,3? – Hasturkun

Antwort

5

Randal Schwartz zeigt einen besseren Weg in Watching long processes through CGI.

Das heißt, Lügen über den Inhaltstyp wird nicht helfen. Das folgende Skript macht genau das, was Sie zu wollen, scheint es unter Windows XP mit Apache 2.2 (in, dass es dauert zehn Sekunden, bis die letzte Zeile der Ausgabe erscheinen soll) tun:

#!/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; 
} 

Nun, wenn Sie HTML senden Sie können nicht vermeiden, dass die meisten Browser warten, bis sie glauben, dass die Seite ausreicht, um mit dem Rendern zu beginnen.

4

Was Sie erreichen wollen, ist möglich - Browser geben im Allgemeinen das, was sie bisher erhalten hat, auch wenn es nicht das komplette Dokument ist, vorausgesetzt es gibt genügend Markup, um überhaupt etwas rendern zu können. Ich frage mich aber, warum Sie \r\n für einige Ausgaben verwenden und nur \n für andere - Sie sollten konsistent sein und \n überall verwenden. Darüber hinaus geben Sie einen Inhaltstyp von text/html an, jedoch keine HTML-Header (<html><title></title><body>) vor Ihrem Inhalt.

Die "moderne" Möglichkeit ist jedoch, die Seitenausgabe sofort zurückzugeben, aber den Teil, den Sie später aktualisieren möchten, als leeres <div> Element zu belassen. Dann können Sie den Inhalt dieses Elements mit Javascript (über eine AJAX-Anfrage) aktualisieren.

+0

versuchte Ausgabe einer gültigen HTML-Seite, immer noch die gleiche Antwort ... – Jibran

0

Erfüllt es, was Sie erwarten, wenn Sie den Inhaltstyp auf text/plain festlegen? Vielleicht verursacht die HTML-Analyse in Ihrem Browser die Verzögerung in der Ausgabe, da Sie kein gültiges HTML ausgeben? (Kein <html> oder < Körper > Tags)

+0

versuchte, die Ausgabeart auf Text/plain, immer noch nichts ... Ausgang ist immer noch verzögert. – Jibran

+0

Welchen Browser benutzen Sie? Wenn der Browser Inhalt schnüffelt, ignoriert er einfach Ihren Inhaltstyp, wenn Sie trotzdem HTML senden. – innaM

2

Angenommen, Sie eine Version von Apache verwenden neuer als 1.3, sollte diese Arbeit. Andernfalls müssen Sie Ihr Skript in ein NPH (No Parsed Headers) CGI konvertieren, was bedeutet, dass der Dateiname das Präfix nph- haben sollte und vollständige HTTP-Header ausgegeben werden sollen, z.

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

sehen die (etwas alt) Apache FAQ für weitere Informationen

2

Um zu sehen, ob Ihr Skript funktioniert, versuchen Sie es mit einem Befehlszeilenprogramm, um eine Verwechslung mit Ihrem Browser zu vermeiden. curl wird zum Beispiel ausgegeben, sobald es Daten empfängt.

Wenn Sie aus einem wichtigen Grund arbeiten, würde ich Ihren derzeitigen Ansatz nicht verwenden.Wenn das Skript viel Zeit benötigt, um es auszuführen, verzweigen Sie es in den Hintergrund (info here) und aktualisieren Sie eine Datei oder Datenbank mit Fortschritt. Sie können dann einen automatisch aktualisierenden (JavaScript oder META-REFRESH) iFrame verwenden, um den Fortschritt anzuzeigen. Sie könnten auch AJAX verwenden, aber das ist ein bisschen komplizierter.

0

Es funktionierte für mich durch Deaktivierung des Deflate-Moduls für diesen bestimmten virtuellen Host.

SetEnv no-gzip 1 

Ich denke, Sie könnten das gleiche Ergebnis mit einem .htaccess-Datei zu erreichen.

Verwandte Themen