Weblog

Progress bar in ... PHP

Background information

I have to import a massive amount of data from Excel to MySQL. Everything fine, except for two details: I have to use set_time_limit(600); to exceed maximum execution time allowed on server (no problem) and during all this process the echo's I have inside the looong loop arent showing on screen. This is worrying, because the person that will perform the import might think anything's gone wrong. So I start looking for a solution...

Getting close

Looks like php comes with some functions to manage the output buffering on screen. They're flush() and ob_flush(). I honestly don't get the difference but as said in the manual, it's best used in conjunction to make sure page contents are shown by browser. We tried in each loop step and voila! It works! Then I start thinking if it'd be possible to show a progress bar in PHP... And it is too! Cannt believe it. Of course, only under some circumstances, but it's so cool. Come and see...

Requirements

This progress bar is only intended in a case where we do not output data on screen while performing a big loop (import process, for instance, or a huge query in parts, etc). If we want to output data we just need to add flush();ob_flush(); to the end of each loop step to make the buffer flush. But instead of outputting data (i.e. a registry per line as loop passes) I think it's more elegant showing a progress bar. So, we wont output data but only information that something is happening.

Solution

We will add the following code before the loop:


echo "<div id='progress' style='position:relative;padding:0px;
width:650px;height:960px;left:25px;'>";

That starts a block (a layer) where we will be showing button-like information as a progress bar, adding the following code inside each loop step:


echo "<div style='float:left;margin:5px 0px 0px 1px;width:2px;
height:12px;background:red;color:red;'> </div>";
flush();
ob_flush();

And we will finish closing the layer once outside the loop and hiding the progress bar with this little script:


echo "</div>";
echo "<script>";
echo "document.getElementById('progress').style.display = 'none';";
echo "</script>";

You can see an example where we simulate a huge job in the data base (actually, we just pause the loop using sleep(1); that pauses each step one second). And here you have the source code of the PHP progress bar. Enjoy it ;)

This technique does not show percentages, though we could make more steps and calculate the maximum returned number of rows and add a proportional counter, etc. I'll leave it to you as homework.

Comments on this entry

  1. 2004-11-02 20:21:40

    • Julio Juarez
    • [e]
    esta muy cool la barra se sacaron un diezzzzzz
  2. 2004-11-03 10:42:24

    Hi Sergi, Thanks for posting this code it's fantastic just what I have been looking for. I had got as far as the flush and ob_flush code to return the html to the browser but hadn't managed to work out the way to add the bar. It's great! Thank You and it seems so obvious now. I think I will make it work with percentages and post the code back to you if you are interested. Thanks again, Darren
  3. 2004-11-03 10:51:39

    hey Darren, so glad you like it ;) I already have that % code done, it's just 2 or 3 lines of code. i added that comment to try to start some small "homeworks feedback" on code-related posts, but thanx, its always great to hear from users

  4. 2004-11-11 06:52:46

    Hey Sergi, I've used a method like this in the past for a project that had some long processing tasks. I echoed out something like this:

    
    <script>
    ProgressBar.Update($percent,'$projectname','$filename');
    </script>
    

    Then the ProgressBar object handles the nice displaying of the bar.

    (For what it's worth, the project I worked on rendered 100s of pages from a server based e-learning development system as HTML and output them in a directory structure with image and script resources, it then zipped them all up and sent them down to the user.)

  5. 2004-11-11 06:54:40

    PS It might be nice to automatically add <br />'s to the messages :)

    Also my last post's <script> tags were stripped out. Maybe a BB-Code type thing would be better.

  6. 2004-11-11 08:35:52

    hey Dan, thanx for the comments! It's awesome, i think it'd work much better than my approach casue javascript would handle all calculations, php would only have to flush the script tags.

    ah, yeah, i have to fix the form to accept bbcode or smth like that, i only accept p, em, strong and links so far but code would be perfect. I'll have a look ;)

  7. 2005-02-12 12:52:08

    This works amazingly well! Thanks!
  8. 2005-03-14 12:21:43

    • hector Barrera
    • [e]
    Este pedazo de codigo es excelente, me haz sacado del mayor apuro que he tenido, muchas gracias. un detalle podriamos colocarle algo de diseno a esa barra?? soy un conchudo. gracias
  9. 2005-05-11 09:20:28

    scsd
  10. 2005-05-13 12:27:46

    Very, very nice script, i searched long time for it. I modificated it a little bit so that only one bar line appear for regardless how many peace of data: for example you recive from SELECT n rows: $n = mysql_num_rows($rs); than: $bc = round($cnt/135); //135 was my experiment for DIV width=450px $bcnt = 1; than in loop: if ($bc==0) { echo " "; } else { if (($bcnt%$bc)==0) { echo " "; } } flush(); ob_flush(); $bcnt++; // if ($bc==0) it's for small data, where $bc will be 0 ... now i have only and each time one bar line independent of data lines count. Gruess Sergio
  11. 2005-09-15 13:26:33

    Muchas gracias por compartir este codigo, aclara muchas cosas...

Closed

Due to spam bullshit this weblog has been closed to comments, it was impossible to keep my blacklist script updated. You can still figure out my email and send me your message. Sorry.

Change preferences

Change preferences

License

Creative Commons 2001-2004. Sergi Meseguer

RSS syndication

rss (1, 2 ), xhtml, css, taw