2009-09-26 6 views

Antwort

2

Erstellen Sie einen Hintergrundprozess und geben Sie die Hintergrundprozess-ID zurück, damit der Benutzer sie später über eine geheime URL überprüfen kann.

16

Die ignore_user_abort Direktive, und ignore_user_abort Funktion sind wahrscheinlich, was Sie suchen: Es sollte Ihnen ermöglichen, die Antwort an den Browser zu senden, und danach noch einige Berechnungen auf Ihrem Server ausführen.

Dieser Artikel könnte Sie interessieren: Verwendung von ignore_user_abort() zu Out-of-Band-Verarbeitung; Zitat:
EDIT 2010-03-22: den Link entfernt (wurde http:// ! waynepan.com/2007/10/11/ ! how-to-use-ignore_user_abort-to-do-process-out-of-band/ pointing - entfernen Sie die Räume und ! wenn Sie versuchen wollen), nach dem Kommentar von @ Joel sehen.

Grundsätzlich, wenn Sie ignore_user_abort(true) in Ihren PHP Skript verwenden, wird das Skript weiter läuft, selbst wenn der Benutzer die esc gedrückt oder in seinem Browser stoppen. Wie verwendest du das ?
Eine Verwendung wäre Inhalt an den Benutzer zurückgeben und ermöglichen die Verbindung geschlossen werden, während Verarbeitung von Dingen, die Benutzerinteraktion nicht benötigen.

Das folgende Beispiel sendet $response an den Benutzer aus, die Verbindung geschlossen wird (wodurch der spinner/Ladebalken Stopp des Browsers) und dann ausführt do_function_that_takes_five_mins();

und das gegebene Beispiel:

ignore_user_abort(true); 
header("Connection: close"); 
header("Content-Length: " . mb_strlen($response)); 
echo $response; 
flush(); 
do_function_that_takes_five_mins(); 

(Es gibt mehr, habe ich nicht kopieren-einfügen)


Beachten Sie, dass Ihre PHP-Skript noch in den max_execution_time und memory_limit Einschränkungen passen muss - das heißt, Sie sollten dies nicht für Manipulationen verwenden, die zu viel Zeit in Anspruch nehmen.

Dies wird auch einen Apache-Prozess verwenden - was bedeutet, dass Sie nicht Dutzende von Seiten haben sollten, die das gleichzeitig tun.

Noch schöner Trick-Erlebnis zu verbessern, denke ich ;-)

+0

Es funktioniert nicht. Sie können dies versuchen, um es zu sehen: ignore_user_abort (true); header ('Content-Type: text/plain'); Header ("Verbindung: Schließen"); Echo 'etwas'; Schlaf (20); Ausgang(); Es dauert immer noch 20 Sekunden zu reagieren. – Mask

+0

Der Link zu "Wie verwende ich ignore_user_abort() zur Out-of-Band-Verarbeitung" enthält Malware (wenn Sie über einen Referrer angezeigt werden, saugen Sie als SO). Sieht so aus, als ob der Blogbesitzer gehackt wurde ... –

+0

@Joel: danke für den Kommentar; Ich habe meine Antwort bearbeitet, um den Link zu entfernen ;; Ich habe gerade die URL verlassen, ohne einen Hyperlink, und mit einer Warnung –

-1

Sie müssen den flush() Anruf die Antwort haben, sofort an den Browser gesendet.

2

Die Art hängt davon ab, was Sie erreichen möchten.

In meinem Fall musste ich eine Reihe von serverseitigen Verarbeitung, mit nur einer minimalen Menge von Daten zurück an den Browser gesendet werden - zusammenfassende Informationen wirklich.

Ich habe versucht, eine Nachricht Absender erstellen - sendet eine E-Mail an über 250 Personen, aber möglicherweise viel mehr (hängt davon ab, wie viele mit dem System registriert haben).

der PHP-Mail-Handler ist schnell, aber für große Zahlen, nicht schnell genug, so war es an der Zeit gebunden. Um das zu umgehen, musste ich das Timeout auf der Server-/PHP-Seite verzögern und den Browser so lange hängen lassen, bis alle Daten zusammengefasst und angezeigt wurden.

Meine Lösung - ein Teaser.

im Wesentlichen, gab ich dem Benutzer eine Nachricht mit einigen anfänglichen Statistiken (der Versuch, diese viele E-Mails zu senden), erstellt 2 DIV-Boxen (eine für den aktuellen Status Info, die zweite für die endgültige Zusammenfassung Info), die Seitenfuß angezeigt, gestartet die Verarbeitung und, wenn fertig, die Zusammenfassung der Informationen aktualisiert. es geht wie folgt:

Beginnen Sie mit dem Sammeln Ihrer Daten, die Sie verarbeiten werden, und erhalten Sie einige zusammenfassende Informationen. In meinem Fall zog ich die Liste der E-Mail-Adressen, validierte sie und zählte sie.

Dann zeigen die "Versuch" info:

echo "Message contents:"; 
echo "<blockquote>$msgsubject<p>$msgbody</blockquote><p>&nbsp;</p>"; 
echo "Attempting <strong>" . $num_rows . "</strong> email addresses."; 

nun einige DIVs schaffen für Status/Abschluss info:

<div id=content name=content> 
<div id=progress name=progress style='border: black 1px solid; width: ".$boxwidth."px; height: 20px;'></div> 
<br> 
</div> 

wobei $ boxwidth die Breite würden Sie Ihre Fortschrittsbalken gerne werden (wird später erklärt)

Beachten Sie, dass sie im Wesentlichen leer sind - wir werden sie später füllen.

Schließlich füllen Sie den Rest der Seite durch Anzeige der Fußzeile der Seite (in meinem Fall habe ich nur die entsprechende Datei "enthalten").

Nun hängt alles noch im Seitenpuffer, entweder auf dem Server (wenn PHP puffert) oder im Browser (weil es noch nicht gesagt wurde, dass wir fertig sind), also lasst es uns dazu bringen geschoben bekommen und/oder angezeigt mit der „ignorieren“ und „spülen“ von oben:

ignore_user_abort(true); 
flush(); 

Nun, da der Browser Sachen angezeigt wird starten, müssen wir die Benutzer etwas zu sehen, so ist hier die tease geben - Wir erstellen eine Statusleiste, die wir im inneren DIV anzeigen, und eine abschließende Nachricht für das äußere DIV.

So, wie Sie Schleife durch Ihre Daten in regelmäßigen Abständen (Ich werde verlassen „wie oft“ bis zu Ihnen, um herauszufinden), geben die folgenden:

set_time_limit (3); 
... 
(process your data here) 
... 
<script>document.getElementById('progress').innerHTML += "<img src='images/progress_red.gif' width: $width height=20 border=0>"</script> 
flush(); 

Dies wird im Wesentlichen der kleine 4x20 stapeln progress_red Bilder nebeneinander, so dass es scheint, dass ein roter Balken über den Bildschirm bewegt wird. In meinem Fall habe ich das 100 Mal gemacht, basierend auf einem Prozentsatz der Nummer, die ich gerade verarbeitet habe. Die "set_time_limit" fügt dem bestehenden Limit 3 Sekunden hinzu, so dass Sie wissen, dass Ihr Skript nicht in die PHP-Zeitlimit-Wand läuft. Passen Sie die 3 Sekunden für Ihre Anwendung nach Bedarf an.

Obwohl die Seite technisch "komplett" ist, wird der JavaScript-Code das DIV-HTML aktualisieren und unsere Fortschrittsleiste wird "verschieben".

wenn alles getan, ich dann berichten, wie viele Elemente tatsächlich verarbeitet und fügen hinzu, dass an der äußeren DIV html und die Seite ist komplett:

<script>document.getElementById('content').innerHTML += "Message was sent to $sentcnt people."</script> 

Der Browser ist glücklich, weil es all seinen Qualifikationen gehabt hat getroffen (Ende der Seite syntaktisch), der Benutzer sieht etwas passiert bis zum Ende, und der Server

Ich neige nicht, Javascript zu verwenden, wenn ich es helfen kann, aber in dem Fall, gab es keine ausgefallenen CSS-Sachen getan Durch das Javascript ist es ziemlich einfach und einfach zu sehen, was los ist und wenig Overhead auf der Browserseite. Und es funktioniert ziemlich reibungslos.

Ich behaupte nicht, dass dies perfekt ist, aber für eine einfache, niedrige Overhead-Lösung funktioniert es für mich, ohne Cronjobs, zusätzliche Warteschlangenmechanismen oder sekundäre Prozesse erstellen zu müssen.

Verwandte Themen