Вопрос по php – Как сбросить данные в браузер, но продолжить выполнение
у меня естьob_start()
и соответствующийob_flush()
, Я хотел бы сбросить часть данных и продолжить выполнение остальных. С помощьюob_flush()
не помогло. Также по возможности отдых должен происходить без показа загрузки в браузере.
EDIT:
Я не хочу использовать ajax
Использование:
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
, Все они после этого закрыли запрос.
ob_flush
пишет буфер. Другими словами,ob_flush
говорит PHP дать Apache (или nginx / lighttpd / что угодно) вывод, а затем PHP забудет об этом. Как только у Apache есть выход, он делает с ним все, что хочет. (Другими словами, послеob_flush
Вы не можете контролировать, будет ли оно немедленно записано в браузер).
Итак, краткий ответ: гарантированного способа сделать это не существует.
Просто предположение, вы, вероятно, ищете AJAX. Всякий раз, когда люди пытаются манипулировать, когда содержимое страницы загружается, как вы делаете, AJAX почти всегда является правильным путем.
Если вы хотите продолжить задачу в фоновом режиме, вы можете использоватьignore_user_abort
, как подробноВотоднако, это часто не оптимальный подход. По сути, вы теряете контроль над этим потоком, и, по моему мнению, поток веб-сервера не относится к области интенсивной обработки.
Я бы попытался извлечь это из материалов, обращенных к сети. Это может означать запись cron или просто порождение фонового процесса изнутри PHP (процесс, который хотя и был запущен изнутри выполнения скрипта, не умрет со скриптом, и скрипт не будет ждать его завершения перед смертью).
Если вы пойдете по этому пути, это будет означать, что вы даже можете создать какую-то систему статуса, если это необходимо. Затем вы можете следить за выполнением и периодически предоставлять пользователю обновления. (Технически вы могли бы сделать систему статуса сignore_user_abort
сценарий тоже, но он не кажется мне чистым.)
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();
}
Как я уже говорил в нескольких комментариях ранее, вам следует остерегаться распаковки вашего контента, так как это изменит длину вашего контента, но не изменит заголовок об этом. Он также может буферизовать ваш вывод, поэтому он не будет немедленно отправлен клиенту.
Вы можете попытаться сообщить apache, чтобы они не распаковывали ваш контент, используяapache_setenv('no-gzip', '1');
, Но это не будет работать, если вы будете использовать правила перезаписи для перехода на свою страницу, так как это также изменит эти переменные среды. По крайней мере, так оно и было для меня.
Более подробные сведения о сбрасывании вашего контента пользователю вруководство.
объясняющая, как этого можно достичь с помощью apache / mod_php в моем блоге здесь:http://codehackit.blogspot.com/2011/07/how-to-kill-http-connection-and.html Надеюсь, это помогает, ура
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
,
second argument is an array to be passed to 'test' function with an indexed array
Примечание. Я не пользуюсьob_start()
в начале сценария.