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
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).
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.
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.)
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 .
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.
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]}
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)
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.
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ę.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