So leeren Sie Daten in den Browser, fahren aber mit der Ausführung fort

Lesezeit: 6 Minuten

Benutzer-Avatar
aWebDeveloper

Ich habe ein ob_start() und ein entsprechendes ob_flush(). Ich möchte einen Teil der Daten löschen und den Rest weiter ausführen. Verwenden ob_flush() hat nicht geholfen. Auch wenn möglich muss der Rest passieren, ohne dass das Laden im Browser angezeigt wird.

BEARBEITEN:

Ich möchte kein Ajax verwenden

  • Soll nach dem ersten ob_flush eine andere Ausgabe angezeigt werden? Oder möchten Sie, dass die Anfrage vollständig abgeschlossen wird, soweit der Client dies erkennen kann, und dann eine Art Verarbeitung im Hintergrund fortgesetzt wird?

    – Korbin

    14. Mai 2012 um 7:34 Uhr

  • Alles, was Sie brauchen, ist flush(), wenn Ihre Ausgabepufferung bereits in php.ini deaktiviert ist, aber damit dies funktioniert, müssen Sie Apache, NginX usw. konfigurieren.

    – PJ Brunet

    13. November 2013 um 1:55 Uhr

Benutzer-Avatar
Zombaya

Ich habe das in der Vergangenheit gemacht und so habe ich es gelöst:

ob_start();

/*
 * Generate your output here
 */ 

// Ignore connection-closing by the client/user
ignore_user_abort(true);

// Set your timelimit to a length long enough for your script to run, 
// but not so long it will bog down your server in case multiple versions run 
// or this script get's in an endless loop.
if ( 
     !ini_get('safe_mode') 
     && strpos(ini_get('disable_functions'), 'set_time_limit') === FALSE 
){
    set_time_limit(60);
}

// Get your output and send it to the client
$content = ob_get_contents();         // Get the content of the output buffer
ob_end_clean();                      // Close current output buffer
$len = strlen($content);             // Get the length
header('Connection: close');         // Tell the client to close connection
header("Content-Length: $len");     // Close connection after $len characters
echo $content;                       // Output content
flush();                             // Force php-output-cache to flush to browser.
                                     // See caveats below.

// Optional: kill all other output buffering
while (ob_get_level() > 0) {
    ob_end_clean();
}

Wie ich bereits in einigen Kommentaren gesagt habe, sollten Sie darauf achten, Ihren Inhalt zu gzippen, da dies die Länge Ihres Inhalts ändert, aber nicht den Header darüber ändert. Es kann auch Ihre Ausgabe puffern, sodass sie nicht sofort an den Client gesendet wird.
Sie könnten versuchen, Apache wissen zu lassen, dass Ihre Inhalte nicht gzip werden sollen, indem Sie verwenden apache_setenv('no-gzip', '1');. Dies funktioniert jedoch nicht, wenn Sie Rewrite-Regeln verwenden, um zu Ihrer Seite zu gelangen, da dann auch diese Umgebungsvariablen geändert werden. Zumindest hat es das für mich getan.

Weitere Einschränkungen zum Freigeben Ihrer Inhalte an den Benutzer finden Sie im Handbuch.

  • Nur zu Ihrer Information, die PHP-Funktion ist ob_get_contentS

    – Bob Gregor

    11. November 2013 um 20:55 Uhr

Benutzer-Avatar
Corbin

ob_flush schreibt den Puffer. Mit anderen Worten, ob_flush weist PHP an, Apache (oder nginx/lighttpd/whatever) die Ausgabe zu geben und PHP sie dann zu vergessen. Sobald Apache die Ausgabe hat, macht er damit, was er will. (Mit anderen Worten, nach ob_flush es liegt außerhalb Ihrer Kontrolle, ob es sofort in den Browser geschrieben wird oder nicht).

Also, kurze Antwort: Es gibt keinen garantierten Weg, das zu tun.

Nur eine Vermutung, Sie suchen wahrscheinlich nach AJAX. Wann immer Leute versuchen, das Laden von Seiteninhalten zu manipulieren, wie Sie es tun, ist AJAX fast immer der richtige Weg.

Wenn Sie eine Aufgabe im Hintergrund fortsetzen möchten, können Sie verwenden ignore_user_abort, wie hier ausgeführt, ist jedoch oft nicht der optimale Ansatz. Sie verlieren im Wesentlichen die Kontrolle über diesen Thread, und meiner Meinung nach gehört ein Webserver-Thread nicht zu einer starken Verarbeitung.

Ich würde versuchen, es aus dem Web zu extrahieren. Dies könnte einen Cron-Eintrag bedeuten oder einfach einen Hintergrundprozess innerhalb von PHP starten (ein Prozess, der zwar innerhalb der Skriptausführung gestartet wurde, stirbt jedoch nicht mit dem Skript, und das Skript wartet nicht darauf, dass es beendet wird, bevor es stirbt).

Wenn Sie diesen Weg gehen, bedeutet dies, dass Sie bei Bedarf sogar eine Art Statussystem erstellen können. Dann könnten Sie die Ausführung überwachen und den Benutzer regelmäßig über den Fortschritt informieren. (Technisch könnte man ein Statussystem mit a erstellen ignore_user_abort-ed-Skript auch, aber es scheint mir nicht so sauber zu sein.)

  • Wenn sich ein neuer Benutzer anmeldet, möchte ich viele Daten speichern. Diese Daten sollten sofort gespeichert werden, aber den Benutzer nicht unterbrechen, dh das Laden im Browser anzeigen

    – ein Webentwickler

    14. Mai 2012 um 7:50 Uhr

Benutzer-Avatar
Afrig Aminuddin

das ist meine Funktion

function bg_process($fn, $arr) {
    $call = function($fn, $arr){
        header('Connection: close');
        header('Content-length: '.ob_get_length());
        ob_flush();
        flush();
        call_user_func_array($fn, $arr);
        };
    register_shutdown_function($call, $fn, $arr);
    }

Wrap die auszuführende Funktion am Ende, nachdem php die Verbindung geschlossen hat. und natürlich hört der Browser auf zu puffern.

function test() {
    while (true) {
        echo 'this text will never seen by user';
        }
    }

So rufen Sie die Funktion auf

bg_process('test'); 

erstes Argument ist callabledas zweite Argument ist ein Array, das mit einem indizierten Array an die ‘test’-Funktion übergeben werden soll

Hinweis: Ich benutze nicht ob_start() am Anfang des Skripts.

Ich habe hier in meinem Blog einen Artikel, der erklärt, wie dies mit Apache/mod_php erreicht werden kann: http://codehackit.blogspot.com/2011/07/how-to-kill-http-connection-and.html Hoffe das hilft, Prost

Wenn Sie PHP-FPM verwenden:

ignore_user_abort(true);
fastcgi_finish_request();

Oben zwei Funktionen sind die Schlüsselfaktoren, die ignore_user_abort verhindert Fehler u fastcgi_finish_request schließt Client-Verbindung.

Benutzer-Avatar
Alex Wilke

fastcgi_finish_request

Diese Funktion überträgt alle Antwortdaten an den Client und beendet die Anfrage. Dadurch können zeitaufwändige Aufgaben ausgeführt werden, ohne dass die Verbindung zum Client offen bleibt.

funktioniert nicht auf Apache. (PHP 5 >= 5.3.3, PHP 7)

Verwenden:

header("Content-Length: $len");

..wo $len ist die Länge der an den Client zu übertragenden Daten.

Ich habe nicht den Hintergrund, um zu wissen, wann und wo dies funktionieren wird, aber ich habe ein paar Browser ausprobiert, und alle kamen sofort zurück mit:

<?PHP 
    header("Content-length:5");
    echo "this is more than 5";
    sleep(5);
?>

Bearbeiten: Chrome, IE und Opera wurden angezeigt thiswährend Firefox angezeigt wurde this is more than 5. Alle haben die Anfrage danach jedoch geschlossen.

  • Deshalb muss die Inhaltslänge genauso lang sein wie der eigentliche Inhalt. Und hüten Sie sich vor gzip, da dies die Länge Ihrer Antwort verändert.

    – Zombaja

    14. Mai 2012 um 8:36 Uhr

  • @Zombaya, ich sehe jedoch nicht, wie das relevant ist. Solange er nicht versucht, seine Ausgabe nach einer bestimmten Menge zu unterbrechen, sollte dies funktionieren, um die Anfrage nach dem Senden der erforderlichen Daten zu beenden.

    – Mähwalker

    14. Mai 2012 um 8:38 Uhr

  • Nun, als ich es versuchte und die Länge nicht mit der tatsächlichen Länge übereinstimmte, wurde die Verbindung nicht immer geschlossen und weiter geladen.

    – Zombaja

    14. Mai 2012 um 8:45 Uhr

  • @Zombaya, warum stimmt die Länge nicht mit der tatsächlichen Länge überein? Warum konnte er nicht einfach tun header("Content-Length: ".strlen($content));

    – Mähwalker

    14. Mai 2012 um 8:46 Uhr

  • Das funktioniert normalerweise, aber wenn Sie Apache so konfiguriert haben, dass es die gzip-Komprimierung auf Ihren ausgegebenen Webseiten verwendet, ändert es den Inhalt Ihrer Antwort, aber nicht den Content-Length-Header. Damit hatte ich in der Vergangenheit etwas Probleme.

    – Zombaja

    14. Mai 2012 um 8:50 Uhr

1018560cookie-checkSo leeren Sie Daten in den Browser, fahren aber mit der Ausführung fort

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy