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?

Sandburg
  • 757
  • 15
  • 28
MB34
  • 4,210
  • 12
  • 59
  • 110
  • 9
    Why are you using output buffering if you specifically *don't* want to buffer output and send it as the page is being processed? – Matti Virkkunen May 14 '10 at 19:29
  • What do you mean? I DO want to output the stuff as it is being processed. Isn't that what I said? – MB34 May 14 '10 at 19:41
  • 4
    Output buffering is for doing exactly the opposite, that is, buffering the output and sending it all at once. Why are you using it? – Matti Virkkunen May 14 '10 at 19:43
  • 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: http://www.drsoft.com/b/Your_very_own_PHP_progress_bar-73 – MB34 May 14 '10 at 19:51
  • "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. – Kip May 14 '10 at 19:54
  • Have you run this script with error reporting turned on? – webbiedave May 14 '10 at 19:55
  • Yes, error reporting is on and the script is currently running on my dev server (localhost) so the buffering is not an issue. – MB34 May 14 '10 at 20:19

7 Answers7

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

Dinah
  • 52,922
  • 30
  • 133
  • 149
Geek Num 88
  • 5,264
  • 2
  • 22
  • 35
  • Well, looky here, I thought output_buffering = Off in php.ini but I was wrong. Looked at the wrong line. – MB34 May 14 '10 at 20:19
  • @MB34 You should mark this answer right if it solved your problem; there's a checkmark to the left you can click – Michael Mrozek May 14 '10 at 20:41
  • I had to add ob_implicit_flush(true) before ob_start() and set output_buffering = Off in php.ini – embe Apr 02 '17 at 09:08
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.

Piotr Pankowski
  • 2,396
  • 1
  • 15
  • 18
  • My mine is 11... But what does that mean? – Ryan Knell Mar 20 '14 at 01:02
  • @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. – Parris Varney May 29 '14 at 18:16
  • 3
    Does this mean that if you call a flush as many times as ob_get_level(); you can return to 0? – Ryan Knell Jun 02 '14 at 03:03
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

Rahul Shinde
  • 853
  • 9
  • 7
3

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

fireweasel
  • 359
  • 5
  • 6
1

Add this line

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

worked for me.

Majid Ramzani
  • 358
  • 5
  • 12
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

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

Kip
  • 107,154
  • 87
  • 232
  • 265