PHP Flush That Works... Even in Nginx

PHP Flush that works... even in Nginx

FINAL SOLUTION

So that's what I found out:

Flush would not work under Apache's mod_gzip or Nginx's gzip because, logically, it is gzipping the content, and to do that it must buffer content to gzip it. Any sort of web server gzipping would affect this. In short, at the server side, we need to disable gzip and decrease the fastcgi buffer size. So:

  • In php.ini:

    . output_buffering = Off

    . zlib.output_compression = Off

  • In nginx.conf:

    . gzip off;

    . proxy_buffering off;

Also have this lines at hand, specially if you don't have acces to php.ini:

  • @ini_set('zlib.output_compression',0);

  • @ini_set('implicit_flush',1);

  • @ob_end_clean();

  • set_time_limit(0);

Last, if you have it, coment the code bellow:

  • ob_start('ob_gzhandler');

  • ob_flush();

PHP test code:

ob_implicit_flush(1);

for($i=0; $i<10; $i++){
echo $i;

//this is for the buffer achieve the minimum size in order to flush data
echo str_repeat(' ',1024*64);

sleep(1);
}

Related:

  • php flush not working

  • How to flush output after each `echo` call?

  • PHP flushing output as soon as you call echo

Flush output buffer in Apache/Nginx setup

You should turn off buffering in nginx:

proxy_buffering off;

Reference: http://nginx.org/r/proxy_buffering

How to disable output buffering in nginx for PHP application

First php has to correctly flush everything :

@ob_end_flush();
@flush();

Then, I found two working solutions:

1) Via Nginx configuration:

fastcgi_buffering off;

2) Via HTTP header in the php code

header('X-Accel-Buffering: no');

php flush not working

You're using ob_flush without ob_start, so there is nothing to flush for it.

It also depends on the webserver and proxy and its settings.

You should disable buffering for Nginx (add proxy_buffering off; to the config file and restart Nginx)

Also, check if your php.ini contains output_buffering = Off and zlib.output_compression = Off.

PHP flush don't work

This works, but only in a default apache environment:

<?php
ini_set('output_buffering', 0);
ini_set('zlib.output_compression', 0);
if( !ob_get_level() ){ ob_start(); }
else { ob_end_clean(); ob_start(); }
for ($i = 0; $i < 10; $i++) {
//For Nginx we have to reach minimum buffer size,
//so if it is not enough increment output
echo str_pad( $i . '<br>', 1024 + 10, ' ', STR_PAD_RIGHT );
flush();
ob_flush();
sleep(1);
}

Nginx needs more configurations:

usually in /etc/nginx/nginx.conf

gzip off;
proxy_buffering off;
fastcgi_buffer_size 1k; #set buffer to 1k
fastcgi_max_temp_file_size 0;
fastcgi_buffers 128 1k; #set max buffer size to 1k + 128*1k

How to flush output after each `echo` call?

Edit:

I was reading the comments on the manual page and came across a bug that states that ob_implicit_flush does not work and the following is a workaround for it:

ob_end_flush();

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_start();

If this does not work then what may even be happening is that the client does not receive the packet from the server until the server has built up enough characters to send what it considers a packet worth sending.


Old Answer:

You could use ob_implicit_flush which will tell output buffering to turn off buffering for a while:

ob_implicit_flush(true);

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_implicit_flush(false);

PHP flushing output as soon as you call echo

The script works fine from CLI, displaying "Fun", waiting 5 secs before displaying "<br>Mo".

For a browser the results might be a bit different because:

  1. The browser wont start rendering right away. Getting 3 bytes of data for HTML document isn't enough to do anything, so it'll most likely wait for a few more.
  2. Implicit IO buffering on the lib level will most likely be active until a newline is received.

To work around 1) use text/plain content type for your test; 2) needs newlines, so do an echo "Fun\n"; and echo "<br>Mo\n"; Of course you wont be using text/plain for real HTML data.



Related Topics



Leave a reply



Submit