PHP: close output stream

Is it possible to close the output of a PHP script? I have a script that needs to do some post-processing, but during and after the subsequent processing, it will no longer send any data to the client, so I would like to close the connection before processing the message.

Edit: In my application, I have a cache that needs to be rebuilt from time to time. However, I do not want to slow down the user. I want to determine at the end of the script if the cache needs to be rebuilt. Therefore, I want to close the output stream first, so the user gets its data, and then I want to rebuild the cache. This is not really important, but I think itโ€™s better to close the connection first, so the user will not notice that the cache is rebuilt if it takes a lot of time.

+6
source share
3 answers

UPDATE

The way to handle this case is a combination of output buffering and associated HTTP headers.

From the HTTP / 1.1 Specification Section 14.10 :

HTTP / 1.1 defines the "close" parameter for the sender to signal that the connection will be closed after the completion of the Response.

So, if we go through the HTTP Content-Length header in addition to Connection: close, the browser knows to close the connection after receiving the specified response length:

  • The ALL script buffer prints so that you retain the ability to send headers
  • Once you get the full output, send the appropriate headers to the client
  • Continue processing ... but do not try to send the output or you will get errors because the headers are sent.

Also, be careful, as you may encounter script runtime limitations in the SAPI web server if you process too much. Finally, you must tell PHP to ignore the โ€œuser interruptโ€ in this particular script using ignore_user_abort() , as the browser will close the connection as a result of what you are doing and you want PHP to continue to process.

 <?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 ... ?> 

You can study the PHP manual section on Handling connection docs .

Alternatively, why not start output buffering? You can then capture all the output that will be sent, and then decide later if you really want to do anything with it.

 <?php echo 'before output buffering'; ob_start(); echo 'after output buffering'; $output = ob_get_contents(); // script only output to this point will be 'before output buffering' // I changed my mind, send the output ... ob_end_flush(); ?> 
+4
source

I don't have enough reputation for comment, but I want to share it in @rdlowrey's answer. gzip can be a problem.

If you have gzip enabled, the Transfer-encoding header is always set to chunked, even if you try to change it with the header("Transfer-encoding: none"); so it wonโ€™t send the Content-Length header.

How could I solve this, I had to use the following:

 <? @ini_set('zlib.output_compression', 'Off'); @ini_set('output_buffering', 'Off'); @ini_set('output_handler', ''); @apache_setenv('no-gzip', 1); ?> 

And then the solution:

 <? 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 ... ?> 
0
source

Source: https://habr.com/ru/post/906698/


All Articles