Jak spłukać dane do przeglądarki, ale kontynuować wykonywanie

Mam ob_start() i odpowiednie ob_flush(). Chciałbym spłukać część danych i kontynuować wykonywanie reszty. Użycie ob_flush() nie pomogło. Również, jeśli to możliwe, reszta musi się zdarzyć bez pokazywania ładowania w przeglądarce.

EDIT:

Nie chcę używać ajax

Author: Ben Everard, 2012-05-14

7 answers

ob_flush zapisuje bufor. Innymi słowy, ob_flush mówi PHP, aby dał Apache (lub nginx/lighttpd/cokolwiek) wyjście, a następnie aby PHP o tym zapomniał. Gdy Apache ma wyjście, robi z nim, co chce. (Innymi słowy, po ob_flush jest poza Twoją kontrolą, czy zostanie natychmiast zapisany do przeglądarki).

Krótka odpowiedź: nie ma na to gwarancji.

Tylko zgaduję, prawdopodobnie szukasz AJAX. Ilekroć ludzie próbują manipuluj, gdy zawartość strony ładuje się tak, jak robisz, AJAX jest prawie zawsze poprawną ścieżką.

Jeśli chcesz kontynuować zadanie w tle, możesz użyć ignore_user_abort, Jak szczegółowo tutaj , jednak często nie jest to optymalne podejście. Zasadniczo tracisz kontrolę nad tym wątkiem, a moim zdaniem wątek serwera www nie jest tam, gdzie należy ciężkie przetwarzanie.

[[5]] starałbym się wydobyć go z sieci. Może to oznaczać wejście crona lub po prostu zrobienie proces w tle z wnętrza PHP (proces, który rozpoczął się od wewnątrz wykonania skryptu nie umrze wraz ze skryptem, a skrypt nie będzie czekał na jego zakończenie przed śmiercią).

Jeśli pójdziesz tą drogą, będzie to oznaczać, że możesz nawet stworzyć jakiś system statusu, jeśli to konieczne. Następnie można monitorować wykonanie i dać użytkownikowi okresowe aktualizacje na postęp. (Technicznie można zrobić system statusu za pomocą skryptu ignore_user_abort-ed, ale nie wydaje się tak czysty, aby ja.)

 16
Author: Corbin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-09 18:33:06

Robiłem to w przeszłości i tak to rozwiązałem:

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();
}

Jak powiedziałem w kilku komentarzach wcześniej, powinieneś uważać na gzipping treści, ponieważ zmieni to długość Twojej treści, ale nie zmieni nagłówka o tym. Może również buforować Twoje dane wyjściowe, dzięki czemu nie zostanie natychmiast wysłane do klienta.
Możesz spróbować poinformować apache, aby nie gzipować treści za pomocą apache_setenv('no-gzip', '1');. Ale to nie zadziała, jeśli użyjesz rewrite-rules, aby przejść do swojej strony, od tego czasu zmodyfikuje również te zmienne środowiskowe. Przynajmniej tak było dla mnie.

Zobacz więcej zastrzeżeń dotyczących spłukiwania Zawartości Użytkownika w instrukcji .

 16
Author: Zombaya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-13 14:25:11

To jest moja funkcja

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);
    }

Zawiń funkcję do wykonania na końcu, po zamknięciu połączenia przez php. i oczywiście przeglądarka przestanie buforować.

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

Oto jak wywołać funkcję

bg_process('test'); 

Pierwszy argument to callable, drugi argument to tablica przekazywana do funkcji 'test' z indeksowaną tablicą

Uwaga: nie używam ob_start() na początku skryptu.

 4
Author: Afrig Aminuddin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-17 06:43:01

Mam artykuł wyjaśniający, jak można to osiągnąć za pomocą apache / mod_php na moim blogu tutaj: http://codehackit.blogspot.com/2011/07/how-to-kill-http-connection-and.html mam nadzieję, że to pomoże, pozdrawiam]}

 2
Author: smassey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-14 07:50:34

fastcgi_finish_request

Ta funkcja spłukuje wszystkie dane odpowiedzi do klienta i kończy żądanie. Pozwala to na czasochłonne wykonywanie zadań bez pozostawienia otwartego połączenia z klientem.

Nie działa na Apache.(PHP 5 >= 5.3.3, PHP 7)

 0
Author: sun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-25 00:31:47

Jeśli używasz PHP-FPM:

ignore_user_abort(true);
fastcgi_finish_request();

Powyższe dwie funkcje są kluczowymi czynnikami, które ignore_user_abort zapobiegają błędom i fastcgi_finish_request zamykają połączenie z klientem.

 0
Author: Nick Tsai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-28 08:37:02

Użycie:

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

..gdzie $len jest długością danych, które mają zostać przesłane do klienta.

Nie mam tła, aby wiedzieć, kiedy i gdzie to będzie działać, ale próbowałem na kilku przeglądarkach i wszystko wróciło natychmiast z:

<?PHP 
    header("Content-length:5");
    echo "this is more than 5";
    sleep(5);
?>
Edit: Chrome, IE i Opera pokazały this, A FireFox pokazały this is more than 5. Po tym jednak wszystkie z nich zamknęły prośbę.
 -1
Author: mowwwalker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-14 07:58:22