PHP: закрыть выходной поток

Возможно ли закрыть выходной поток скрипта PHP? У меня есть сценарий, который должен выполнять некоторую пост-обработку, но во время и после последующей обработки он больше не будет отправлять какие-либо данные клиенту, поэтому я хотел бы закрыть соединение до обработки сообщения.

Изменить. В моем приложении у меня есть кеш, который нужно перестраивать время от времени. Однако я не хочу замедлять пользователя. То, что я хочу, – это определить в конце скрипта, если кеш нужно перестроить. Поэтому я хочу сначала закрыть выходной поток, поэтому пользователь получает его данные, а затем я хочу восстановить кеш. На самом деле это не так важно, но я думаю, что лучше сначала закрыть соединение, поэтому пользователь не заметит, что кеш перестраивается, если это занимает много времени.

ОБНОВИТЬ

Способ обработки этого случая – комбинация буферизации вывода и соответствующих заголовков HTTP.

Из раздела спецификации HTTP / 1.1 14.10 :

HTTP / 1.1 определяет параметр «закрыть» для отправителя, чтобы сигнализировать о том, что соединение будет закрыто после завершения ответа.

Итак, если мы передаем заголовок HTTP Content-Length в дополнение к Connection: close , браузеру известно закрыть соединение после получения указанной длины ответа:

  1. Буфер ВСЕ вывод сценария, чтобы сохранить возможность отправки заголовков
  2. После того как вы получите полные выходные данные, отправьте соответствующие заголовки клиенту
  3. Продолжайте обработку … но не пытайтесь отправить вывод или вы получите ошибки, потому что отправлены заголовки.

Кроме того, будьте осторожны, так как вы можете столкнуться с ограничениями времени выполнения скриптов в веб-сервере 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(); ?> 

У меня недостаточно репутации для комментариев, но я хочу поделиться этим в ответ @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 ... ?>