How to flush output after each `echo` call?

PhpApacheEchoFlush

Php Problem Overview


I have a php script that only produces logs to the client.
When I echo something, I want it to be transferred to client on-the-fly.
(Because while the script is processing, the page is blank)
I had already played around with ob_start() and ob_flush(), but they didn't work.

What's the best solution?

PS: it is a little dirty to put a flush at the end of the echo call...

EDIT: Neither the Answers worked, PHP or Apache Fault?

Php Solutions


Solution 1 - Php

I've gotten the same issue and one of the posted example in the manual worked. A character set must be specified as one of the posters here already mentioned. http://www.php.net/manual/en/function.ob-flush.php#109314

header( 'Content-type: text/html; charset=utf-8' );
echo 'Begin ...<br />';
for( $i = 0 ; $i < 10 ; $i++ )
{
	echo $i . '<br />';
	flush();
	ob_flush();
	sleep(1);
}
echo 'End ...<br />';

Solution 2 - Php

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);

Solution 3 - Php

So here'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 these lines at hand, especially if you don't have access 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, comment 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 to make the buffer achieve the minimum size in order to flush data
	echo str_repeat(' ',1024*64);

	sleep(1);
}

Solution 4 - Php

For those coming in 2018:

The ONLY Solution worked for me:

<?php

    if (ob_get_level() == 0) ob_start();
    for ($i = 0; $i<10; $i++){

        echo "<br> Line to show.";
        echo str_pad('',4096)."\n";    

        ob_flush();
        flush();
        sleep(2);
    }

    echo "Done.";

    ob_end_flush();
?>

and its very important to keep de "4096" part because it seems that "fills" the buffer...

Solution 5 - Php

Flushing seemingly failing to work is a side effect of automatic character set detection.

The browser will not display anything until it knows the character set to display it in, and if you don't specify the character set, it need tries to guess it. The problem being that it can't make a good guess without enough data, which is why browsers seem to have this 1024 byte (or similar) buffer they need filled before displaying anything.

The solution is therefore to make sure the browser doesn't have to guess the character set.

If you're sending text, add a '; charset=utf-8' to its content type, and if it's HTML, add the character set to the appropriate meta tag.

Solution 6 - Php

what you want is the flush method. example:

echo "log to client";
 flush();

Solution 7 - Php

Why not make a function to echo, like this:

function fecho($string) {
 echo $string;
 ob_flush();
}

Solution 8 - Php

I had a similar thing to do. Using

// ini_set("output_buffering", 0);  // off 
ini_set("zlib.output_compression", 0);  // off
ini_set("implicit_flush", 1);  // on   

did make the output flushing frequent in my case.

But I had to flush the output right at a particular point(in a loop that I run), so using both

ob_flush();
flush();

together worked for me.

> I wasn't able to > turn off "output_buffering" with > ini_set(...), had to turn it directly > in php.ini, phpinfo() shows its setting > as "no value" when turned off, is that > normal? .

Solution 9 - Php

One thing that is not often mentionned is gzip compression that keeps turned ON because of details in various hosting environments.

Here is a modern approach, working with PHP-FPM as Fast CGI, which does not need .htaccess rewrite rule or environment variable :

In php.ini or .user.ini :

output_buffering = 0
zlib.output_compression = 0
implicit_flush = true
output_handler = 

In PHP script :

header('Content-Encoding: none'); // Disable gzip compression
ob_end_flush(); // Stop buffer
ob_implicit_flush(1); // Implicit flush at each output command

See this comment on official PHP doc for ob_end_flush() need.

Solution 10 - Php

The correct function to use is flush().

<html>
<body>
<p>
Hello! I am waiting for the next message...<br />
<?php flush(); sleep(5); ?>
I am the next message!<br />
<?php flush(); sleep(5); ?>
And I am the last message. Good bye.
</p>
</body>
</html>

Please note that there is a "problem" with IE, which only outputs the flushed content when it is at least 256 byte, so your first part of the page needs to be at least 256 byte.

Solution 11 - Php

This works fine for me (Apache 2.4/PHP 7.0):

@ob_end_clean();
echo "lorem ipsum...";
flush();
sleep(5);
echo "<br>dolor...";
flush();
sleep(5);
echo "<br>sit amet";

Solution 12 - Php

header( 'X-Accel-Buffering: no' );
header( 'Content-Type: text/html; charset=utf-8' );

echo 'text to display';
echo '<span style="display: none;">' . str_repeat ( ' ', 4096 ) . '</span>';
flush();
usleep( 10 );

Solution 13 - Php

Anti-virus software may also be interfering with output flushing. In my case, Kaspersky Anti-Virus 2013 was holding data chunks before sending it to the browser, even though I was using an accepted solution.

Solution 14 - Php

Sometimes, the problem come from Apache settings. Apache can be set to gzip the output. In the file .htaccess you can add for instance :

SetEnv no-gzip 1

Solution 15 - Php

Try this:

while (@ob_end_flush());      
ob_implicit_flush(true);

echo "first line visible to the browser";
echo "<br />";

sleep(5);
    
echo "second line visible to the browser after 5 secs";

Just notice that this way you're actually disabling the output buffer for your current script. I guess you can reenable it with ob_start() (i'm not sure).

Important thing is that by disabling your output buffer like above, you will not be able to redirect your php script anymore using the header() function, because php can sent only once per script execution http headers. You can however redirect using javascript. Just let your php script echo following lines when it comes to that:

        echo '<script type="text/javascript">';
        echo 'window.location.href="'.$url.'";';
        echo '</script>';
        echo '<noscript>';
        echo '<meta http-equiv="refresh" content="0;url='.$url.'" />';
        echo '</noscript>'; 
        exit;

Solution 16 - Php

Note if you are on certain shared hosting sites like Dreamhost you can't disable PHP output buffering at all without going through different routes:

> Changing the output buffer cache If you are using PHP FastCGI, the PHP > functions flush(), ob_flush(), and ob_implicit_flush() will not > function as expected. By default, output is buffered at a higher level > than PHP (specifically, by the Apache module mod_deflate which is > similar in form/function to mod_gzip). > > If you need unbuffered output, you must either use CGI (instead of > FastCGI) or contact support to request that mod_deflate is disabled > for your site.

https://help.dreamhost.com/hc/en-us/articles/214202188-PHP-overview

Solution 17 - Php

I'm late to the discussion but I read that many people are saying appending flush(); at the end of each code looks dirty, and they are right.

Best solution is to disable deflate, gzip and all buffering from Apache, intermediate handlers and PHP. Then in your php.ini you should have:

			output_buffering = Off
			zlib.output_compression = Off
			implicit_flush = Off

Temporary solution is to have this in your php.ini IF you can solve your problem with flush(); but you think it is dirty and ugly to put it everywhere.

implicit_flush = On

If you only put it above in your php.ini, you don't need to put flush(); in your code anymore.

Solution 18 - Php

This is my code: (work for PHP7)

private function closeConnection()
{
    @apache_setenv('no-gzip', 1);
    @ini_set('zlib.output_compression', 0);
    @ini_set('implicit_flush', 1);

    ignore_user_abort(true);
    set_time_limit(0);

    ob_start();
    // do initial processing here
    echo json_encode(['ans' => true]);

    header('Connection: close');
    header('Content-Length: ' . ob_get_length());
    ob_end_flush();
    ob_flush();
    flush();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncusspvzView Question on Stackoverflow
Solution 1 - PhpTenoView Answer on Stackoverflow
Solution 2 - PhpamphetamachineView Answer on Stackoverflow
Solution 3 - PhpRogerView Answer on Stackoverflow
Solution 4 - PhpAri WaisbergView Answer on Stackoverflow
Solution 5 - PhpnobodyView Answer on Stackoverflow
Solution 6 - PhpGStoView Answer on Stackoverflow
Solution 7 - Phpcam8001View Answer on Stackoverflow
Solution 8 - PhpfreedayumView Answer on Stackoverflow
Solution 9 - PhpZalemCitizenView Answer on Stackoverflow
Solution 10 - PhpDennis GView Answer on Stackoverflow
Solution 11 - PhpRadacinaView Answer on Stackoverflow
Solution 12 - PhpJevgeni VirvesView Answer on Stackoverflow
Solution 13 - PhpmarcovtwoutView Answer on Stackoverflow
Solution 14 - PhpjlguenegoView Answer on Stackoverflow
Solution 15 - PhpGrigoreas P.View Answer on Stackoverflow
Solution 16 - PhpMatthew LockView Answer on Stackoverflow
Solution 17 - PhpTarikView Answer on Stackoverflow
Solution 18 - PhpDmitry MatrosovView Answer on Stackoverflow