У меня есть ob_start()
и соответствующий ob_flush()
. Я хотел бы очистить часть данных и продолжить выполнение остальных. Использование ob_flush()
не помогло. Также, если это возможно, отдых должен происходить без отображения загрузки в браузере.
РЕДАКТИРОВАТЬ:
Я не хочу использовать ajax
ob_flush
пишет буфер. Другими словами, ob_flush
сообщает PHP, чтобы предоставить выход Apache (или nginx / lighttpd / whatever), а затем PHP забыть об этом. Как только Apache имеет выход, он делает все, что захочет. (Другими словами, после ob_flush
это не ob_flush
от того, сразу ли он сразу же попадает в браузер).
Итак, короткий ответ: нет никакого гарантированного способа сделать это.
Просто предположим, вы, скорее всего, ищете AJAX. Всякий раз, когда люди пытаются манипулировать при загрузке содержимого страницы, как вы делаете, AJAX почти всегда правильный путь.
Если вы хотите продолжить задачу в фоновом режиме, вы можете использовать ignore_user_abort
, как подробно описано здесь , однако это часто не оптимальный подход. Вы по существу теряете контроль над этим потоком, и, на мой взгляд, поток веб-сервера не там, где тяжелая обработка принадлежит.
Я бы попытался извлечь его из Интернета. Это может означать запись cron или просто генерирование фонового процесса изнутри PHP (процесс, который, хотя и запущен изнутри выполнения скрипта, не будет умирать со сценарием, и сценарий не дожидается, пока он закончит до того, как он умрет).
Если вы поедете по этому маршруту, это будет означать, что вы можете даже сделать какую-то систему статуса, если это необходимо. Затем вы можете следить за выполнением и периодически предоставлять пользователям обновления. (Технически вы могли бы создать систему состояния с помощью ignore_user_abort
-ed, но для меня это не кажется таким же чистым).
Я сделал это в прошлом, и именно так я решил это:
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(); }
Как я уже сказал в нескольких комментариях, вы должны следить за gzipping вашего контента, поскольку это изменит длину вашего контента, но не изменит заголовок об этом. Он также может буферизовать ваш вывод, поэтому он не получит немедленную отправку клиенту.
Вы можете попытаться позволить apache знать, чтобы не gzip ваш контент, используя apache_setenv('no-gzip', '1');
, Но это не сработает, если вы используете правила перезаписи, чтобы перейти на вашу страницу, так как тогда он также изменит эти переменные среды. По крайней мере, он сделал это для меня.
См. Дополнительные предупреждения о том, как очистить свой контент от пользователя в руководстве .
это моя функция
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); }
завершите функцию, которая будет выполнена в конце, после того, как php закроет соединение. и, конечно, браузер остановит буферизацию.
function test() { while (true) { echo 'this text will never seen by user'; } }
это как вызвать функцию
bg_process('test');
первый аргумент callable
, второй аргумент – это массив, который должен быть передан функции «test» с индексированным массивом
Примечание. Я не использую ob_start()
в начале скрипта.
У меня есть статья, объясняющая, как это может быть достигнуто с помощью apache / mod_php в моем блоге здесь: http://codehackit.blogspot.com/2011/07/how-to-kill-http-connection-and.html Надеюсь, что это поможет, ура
Использование:
header("Content-Length: $len");
где $len
– длина данных, которые должны быть сброшены клиенту.
У меня нет фона для того, чтобы знать, когда и где это будет работать, но я попробовал несколько браузеров, и все они мгновенно возвращались:
<?PHP header("Content-length:5"); echo "this is more than 5"; sleep(5); ?>
Редактировать: Chrome, IE и Opera показали this
, в то время как FireFox показал, что this is more than 5
. Однако все они закрыли запрос.