PHP Flush() not working in Chrome

2019-01-14 17:54发布

问题:

I stumbled upon this function which promised to work across IE, FF & Chrome. But it does not work in Chrome. Is there a work around?

function buffer_flush(){

    echo str_pad('', 512);
    echo '<!-- -->';

    if(ob_get_length()){

        @ob_flush();
        @flush();
        @ob_end_flush();

    }

    @ob_start();
}

回答1:

Here's how I got flush() working in a while loop in Chrome 12.0.742.122 with PHP 5.3.6:

echo("<html><body>");
while(1) {
  echo(str_pad($my_string_var,2048," "));
  @ob_flush();
  flush();
}

Using a lesser str_pad value worked too, but it would take a bit longer for the first output to appear. If any of the other lines were missing, nothing would appear.

The "@" isn't strictly necessary, but it prevents the log from filling up with "nothing in the buffer" notices.

And of course if you have a pre-existing page, just make sure the <html> and <body> tags are in there; I was writing a page from scratch.



回答2:

With flush()/ob_flush() you only send the output to the browser, but its still up to the browser, when it displays it. I assume, that chrome just waits, until it has enough data received to display a "useful" page, instead of some fragments.

Some suggestions anyway:

  • Avoid using @ (especially if you don't know exactly, what it does)
  • If you don't call ob_end_*(), you don't need to call ob_start() again. Its inefficient

    function buffer_flush(){
      echo '<!-- -->'; // ?
    
      ob_flush();
      flush();
    }
    


回答3:

Some browsers (IE6 at the very least, and possibly chrome) require a certain amount of "useful" characters (i.e. not spaces) before outputting anything. In the case of IE6, it even is the compressed data's size that needs to be pushed.

function force_flush() {
    echo "\n\n<!-- Deal with browser-related buffering by sending some incompressible strings -->\n\n";

    for ( $i = 0; $i < 5; $i++ )
        echo "<!-- abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono -->\n\n";

    while ( ob_get_level() )
        ob_end_flush();

    @ob_flush();
    @flush();
} # force_flush()


回答4:

There are several components that can have impact on this issue.

Read carefully through the documentation of this function: http://www.php.net/manual/en/function.flush.php

One solution I had was using Apache2 with mod-php (not as fcgi but as native apache-module) and Chromium. The result came immediately and the script was still running and sending more results.

After typing the following two code-lines every echo-command will immediately push the text to the whatever-PHP-backend:

ob_implicit_flush(1);
@ob_end_flush(); // set an end to the php-output-buffer!

But this php backend can have its own buffer. For example I run nginx as webserver and php is used by the fast-cgi module. Nginx itself has its own buffer ... and so on.

The Browser also can buffer the request. But as I experience Chromium (or Google Chrome) has a verry small or no buffer.

Please read the documentation of every function I mentioned to understand what they really do - but specially the documentation of flush().

Personal hint: Do not put extra characters into the output-buffer but read and understand the configuration of your server.

EDIT: If you have gzip enabled the whole response from the server will be buffered.



回答5:

I found that a content type header really makes it work in chrome after few trial and errors.

But i don't know why chrome does not flush otherwise.

after searching for more answers i read that chrome flushes as you expect only when a valid content type is set. fine.

Here is the code i experimented.

<?php
header('Content-Type: text/html; charset=UTF-8');

echo 'starting...';
flush();
echo 'to sleep...';
flush();
sleep(5);
echo 'awake';

if i do not include the content type header i get like the following in one shot after 5 seconds. so what we expect did not work.

starting...to sleep...awake is displayed and the script terminates.

where as when i gave the content type like the above with the subtype(charset) then

starting...to sleep... is displayed immediately and then after 5 seconds awake is displayed.

i am just blindly assuming that with respect to the content type header chrome shows the output.

Besides when i gave 'Content-Type: text/plain' or 'Content-Type: text/html' it did not work. it worked only with the subtype 'charset=[sometexthere]'.

were as application/json worked. and i did not experiment with more mimes.

The reason i am here is

i wanted to use readystate 3 in ajax response. it works fine except chrome and safari. since chrome is using webkit it is the same in both i think.

in other browsers including IE the flushing is working as expected and also the readystate=3 but in chrome and safari i just used the above workaround.

here is the screenshot of the readystate - responsetext from the above php script

in the image there a two sets of response the first one with readystate 3 and responsetext as empty when content type is not used.

in the second response you can see ready state 3 has responsetext with the expected output. this is when content type is used.

so... Chrome only knows.

when used str_pad

When you use string padding you can get more expected result. i tried with 1024 as the above answers suggested but only with content type set.

if padding is used and no content type is set then it did not work.

and

i had raised a question similar to this and i am going to add my own answer by linking this answer to that and back to back... so that it will be easy for users to get more details. hhmmm.