Methods ob_start and ob_flush don't work, why?
Asked Answered
C

7

11

I am using ob_start()/ob_flush() to, hopefully, give me some progress during a long import operation.

Here is a simple outline of what I'm doing:

<?php
ob_start ();

echo "Connecting to download Inventory file.<br>";
$conn = ftp_connect($ftp_site) or die("Could not connect");

echo "Logging into site download Inventory file.<br>";
ftp_login($conn,$ftp_username,$ftp_password) or die("Bad login credentials for ". $ftp_site);

echo "Changing directory on download Inventory file.<br>";
ftp_chdir($conn,"INV") or die("could not change directory to INV");

//      connection, local, remote, type, resume
$localname = "INV"."_".date("m")."_".date('d').".csv";
echo "Downloading Inventory file to:".$localname."<br>";

ob_flush();
flush();
sleep(5);

if (ftp_get($conn,$localname,"INV.csv",FTP_ASCII)) 
{
    echo "New Inventory File Downloaded<br>";
    $datapath = $localname;
    ftp_close($conn);
} else {
    ftp_close($conn);
    die("There was a problem downloading the Inventory file.");      
}
ob_flush();
flush();
sleep(5);

$csvfile = fopen($datapath, "r"); // open csv file
$x = 1;
// skip the header line
$line = fgetcsv($csvfile);
$y = (feof($csvfile) ? 2 : 5);
while ((!$debug) ? (!feof($csvfile)) : $x <= $y) {
    $x++;
    $line = fgetcsv($csvfile);
    // do a lot of import stuff here with $line
    ob_flush();
    flush();
    sleep(1);
}

fclose($csvfile); // important: close the file
ob_end_clean();

However, nothing is being output to the screen at all.

I know the data file is getting downloaded because I watch the directory where it is being placed.

I also know that the import is happening, meaning that it is in the while loop, because I can monitor the DB and records are being inserted.

Any ideas as to why I am not getting output to the screen?

Cecillececily answered 14/5, 2010 at 19:27 Comment(7)
Why are you using output buffering if you specifically don't want to buffer output and send it as the page is being processed?Aec
What do you mean? I DO want to output the stuff as it is being processed. Isn't that what I said?Cecillececily
Output buffering is for doing exactly the opposite, that is, buffering the output and sending it all at once. Why are you using it?Aec
I was looking for a way to send the buffer DURING processing instead of having to wait until the entire script processed, like PHP usually does. This would be kind of like a progress system. Including ob_flush() should output the buffer to the display immediately .vs waiting for the script to finish. Should work kind of like this: drsoft.com/b/Your_very_own_PHP_progress_bar-73Cecillececily
"instead of having to wait until the entire script processed, like PHP usually does" Actually, this is not how PHP usually works. Output buffering, as @Matti said, is how you get PHP to act that way. If it is already acting that way for you, then it is because your webserver is doing its own buffering/caching.Holmic
Have you run this script with error reporting turned on?Pietism
Yes, error reporting is on and the script is currently running on my dev server (localhost) so the buffering is not an issue.Cecillececily
A
18

You also need to check the PHP settings

some installs default to 4096, some default to off

output_buffering = Off
output_buffering = 4096

agreed with George but do check the above settings

Alisun answered 14/5, 2010 at 19:48 Comment(3)
<egg on face>Well, looky here, I thought output_buffering = Off in php.ini but I was wrong. Looked at the wrong line.</egg on face>Cecillececily
@Cecillececily You should mark this answer right if it solved your problem; there's a checkmark to the left you can clickKrol
I had to add ob_implicit_flush(true) before ob_start() and set output_buffering = Off in php.iniZanazander
A
17

Make sure that your output buffering doesn't start automatically. Run:

print ob_get_level ();

before ob_start (); if will will see something else then 0 you've got the answer.

Abacus answered 14/5, 2010 at 19:50 Comment(3)
My mine is 11... But what does that mean?Valdis
@ryanknell I means that you're 11 levels of buffering deep, or that you've called ob_start() 11 times since you last flushed it. Flushing will only return output captured at the current level of buffering.Alanis
Does this mean that if you call a flush as many times as ob_get_level(); you can return to 0?Valdis
B
7

Hey man I was also got stuck in this problem and finally got the correct solution here it is for you

you have to add content type for your page you can do that by two ways 1. using html tag

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

Ex.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Wp Migration</title>
</head>
<body>
<?php 
for($i=0;$i<70;$i++)
{
echo 'printing...<br>';
ob_flush();
flush();
sleep(3);
}
?>
</body>
</html>
  1. using php header function

    <?php header( 'Content-type: text/html; charset=utf-8' ); ?>

Ex.

<?php 
header( 'Content-type: text/html; charset=utf-8' );
for($i=0;$i<70;$i++)
{
echo 'printing...<br>';
ob_flush();
flush();
sleep(3);
}
?>

All the best

Boykins answered 12/6, 2013 at 13:8 Comment(0)
D
3

Ob_end_clean() discards the contents of the current output buffer and turns off the buffering. You should use ob_end_flush() instead.

Diego answered 14/5, 2010 at 19:41 Comment(1)
He's calling ob_flush() throughout the script thoughKrol
P
1

Add this line

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

worked for me.

Palmetto answered 17/1, 2019 at 8:25 Comment(0)
C
0

You can edit it with the .htaccess file

To disable output buffering, modify the line as follows:

php_value output_buffering Off
php_value output_buffering 4096

worked for me. Thank you!

Check this site: Click Here

Caloric answered 30/10, 2020 at 13:57 Comment(0)
H
-1

It's possible that your webserver is doing its own buffering. Probably with something like mod_gzip.

Here is some very simple test code:

<?php
echo 'starting...<br/>';
for($i = 0; $i < 5; $i++) {
  print "$i<br/>";
  flush();
  sleep(2);
}
print 'DONE!<br/>';

If it takes 10 seconds for that page to load, rather than seeing a new line every 2 seconds, then it means that it is being cached by your webserver. For what you are trying to do, there is no need to use ob_start and ob_flush. Just call flush whenever you want to force the content to the browser. However, like I mentioned, if the webserver is waiting for the content to complete before sending, then that won't do anything for you.

Edit: Another possibility is that you're viewing the page from behind a corporate or ISP proxy/firewall that waits for the whole page before serving it (so that it can scan it to see if it looks like pornography, for example).

Holmic answered 14/5, 2010 at 19:52 Comment(1)
After setting output_buffering =Off, this worked like it should.Cecillececily

© 2022 - 2024 — McMap. All rights reserved.