Возможно ли закрыть выходной поток скрипта PHP? У меня есть сценарий, который должен выполнять некоторую пост-обработку, но во время и после последующей обработки он больше не будет отправлять какие-либо данные клиенту, поэтому я хотел бы закрыть соединение до обработки сообщения.
Изменить. В моем приложении у меня есть кеш, который нужно перестраивать время от времени. Однако я не хочу замедлять пользователя. То, что я хочу, – это определить в конце скрипта, если кеш нужно перестроить. Поэтому я хочу сначала закрыть выходной поток, поэтому пользователь получает его данные, а затем я хочу восстановить кеш. На самом деле это не так важно, но я думаю, что лучше сначала закрыть соединение, поэтому пользователь не заметит, что кеш перестраивается, если это занимает много времени.
ОБНОВИТЬ
Способ обработки этого случая – комбинация буферизации вывода и соответствующих заголовков HTTP.
Из раздела спецификации HTTP / 1.1 14.10 :
HTTP / 1.1 определяет параметр «закрыть» для отправителя, чтобы сигнализировать о том, что соединение будет закрыто после завершения ответа.
Итак, если мы передаем заголовок HTTP Content-Length в дополнение к Connection: close , браузеру известно закрыть соединение после получения указанной длины ответа:
Кроме того, будьте осторожны, так как вы можете столкнуться с ограничениями времени выполнения скриптов в веб-сервере SAPI, если вы слишком много обрабатываете. Наконец, вы должны сказать PHP игнорировать «пользовательский прерывание» в этом конкретном скрипте, используя ignore_user_abort()
потому что браузер закроет соединение в результате того, что вы делаете, и вы хотите, чтобы PHP продолжал обрабатывать.
<?php ignore_user_abort(); ob_start(); // do stuff, generate output // get size of the content $length = ob_get_length(); // tell client to close the connection after $length bytes received header('Connection: close'); header("Content-Length: $length"); // flush all output ob_end_flush(); ob_flush(); flush(); // close session if you have one ... // continue your processing tasks ... ?>
Вы можете изучить раздел руководства PHP в документации по подключению .
В качестве альтернативы, почему бы не начать буферизацию вывода? Затем вы можете захватить весь вывод, который будет отправлен, а затем решить позже, если вы действительно хотите что-либо сделать с ним.
<?php echo 'before output buffering'; ob_start(); echo 'after output buffering'; $output = ob_get_contents(); // script's only output to this point will be 'before output buffering' // I changed my mind, send the output ... ob_end_flush(); ?>
fclose(STDOUT)
: http://php.net/manual/en/features.commandline.io-streams.php
У меня недостаточно репутации для комментариев, но я хочу поделиться этим в ответ @rdlowrey. Gzip может быть проблемой.
Если у вас включен gzip, заголовок Transfer-encoding всегда устанавливается на chunked , даже если вы попытаетесь изменить его с header("Transfer-encoding: none");
поэтому он не отправляет заголовок Content-Length .
Способ, которым я мог решить это, заключался в следующем:
<? @ini_set('zlib.output_compression', 'Off'); @ini_set('output_buffering', 'Off'); @ini_set('output_handler', ''); @apache_setenv('no-gzip', 1); ?>
И тогда решение:
<? ignore_user_abort(); ob_start(); // do stuff, generate output // get size of the content $length = ob_get_length(); // tell client to close the connection after $length bytes received header('Connection: close'); header("Content-Length: $length"); // flush all output ob_end_flush(); flush(); // close session if you have one ... // continue your processing tasks ... ?>