There and Back Again

PHP AJAX File Upload Progress Meter Updates

Over the weekend my file upload progress meter code got lots of traffic. It seems it made it made it on the del.icio.us popular list as well as getting over a thousands diggs. To celebrate this i’ve updated the code.

The main new feature is giving you feedback without having to patch PHP. Now the patched version gives you more information such as upload speed and estimated time to completion. But we still provide some nice user feedback even without it now.

I also created some wiki pages to start the documentation process.

So here are the demo’s

With the patch and extension
Without the patch

To get upload speed you will need to download and install the PHP Upload Progress Patch and extension.

If you want to use the code you need to:
Install HTML_AJAX (pear install HTML_AJAX-alpha)
Download PAFUPMU and install it somewhere accessible.
Add the code to your page using demo.php as an example.

The basic way the code works is we take a form containing a file upload and submit it using a hidden iframe as a target. Doing this lets the upload happen in the background. Then we poll the server on a regular basis (say a 2 second interval) asking it for update status. If you have the patch+extension installed this gives you file upload speed etc. If you don’t have the extesion we stop making AJAX calls and just animate the status bar until the upload finishes in the iframe and tells us were done.

In demo.php we handle generating the current page and handling the upload in the same page. So we start by handling the update.

include 'UploadProgressMeter.class.php';

$fileWidget = new UploadProgressMeter();

if ($fileWidget->uploadComplete()) {
        // output javascript to the iframe to send a final status to the main window
        // this will catch error conditions
        echo $fileWidget->finalStatus();

        // move the file(s) where they need to go

        exit;
}
?>

This code only runs when your uploading so you’ll never see the output of it. This can make debugging problematic. One way around this is too hack the UploadProgressMeter to make the iframe non hidden.

Next you setup the JavaScript needed, first HTML_AJAX and then the uploaders JS.

        
        
        < ?php echo $fileWidget->renderIncludeJs(); ?>

demoserver.php is included in the source, you might want to name it something else if you actually use this code. Its just a page using HTML_AJAX_Server to register the UploadProgressMeterStatus class

You also need some CSS to style the progress bar. The only important thing is that .progressBar and .progressBar .bar are relatively positioned.

.progressBar {
                position: relative;
                padding: 2px;
                width: 300px;
                height: 40px;
                font-size: 14px;
        }
        .progressBar .background {
                border: solid 1px black;
                width: 270px;
                height: 20px;
        }
        .progressBar .bar {
                position: relative;
                background-color: blue;
                width: 0px;
                height: 20px;
        }

Finally you finish things up by building a form. Note that you can include other elements in the form, but if they need to produce output you’ll have to manage calling back into the parent page from the iframes output.

renderFormExtra(); ?>> < ?php echo $fileWidget->renderHidden(); ?>
< ?php echo $fileWidget->render(); ?> < ?php echo $fileWidget->renderProgressBar(); ?>

131 thoughts on “PHP AJAX File Upload Progress Meter Updates

  1. Pingback: There and Back Again » Blog Archive » AJAX File upload Progress

  2. Pingback: Scriptorama » Files uploaden met progressbar

  3. sam

    Is there a way to do this in reverse? Say I want to make sure a user checks out a file from my server. How do I ensure they actually got the file? How would you handle a partial download, disconnected or canceled, and force them to start over and make sure the file is still set as an in state until they actually download the entire file?

  4. Michael

    Im rather confused, what patch and extention are you talking about? Ive only managed to show an animated ststus bar…

    Thanks

  5. Mark

    Ignore my last comment, I figured it out 😉

    Basically you need to create the $fileWidge->name field in a loop like:

    renderFormExtra(); ?>>
    Select File:

    renderHidden();
    for ($i=1;$iname=”upload_$i”;
    print $fileWidget->render();
    }
    print ($fileWidget->renderProgressBar());
    ?>

    and remove the bits in UploadProgressMeter.class.php that test if the id has already been set (so it is set again).

    I also found a problem if $this->progressId was using $this->name the progress bar didnt complete, so I just set the progressID to a static name (like progress_bar) and then it worked.

    That sorted it for me 🙂

  6. Noam

    Oleh!

    i’ve been looking for something like this for hours now,
    and this is the first one that worked.
    only trouble is, i don’t get how to set the output directory.
    (where will the file be saved..).
    can anyone help with this?

  7. Joshua Eichorn Post author

    You handle dealing with the uploaded files below the comment:
    // move the file(s) where they need to go

    If you have any debugging output at this step you won’t see it, it happens in a hidden iframe.

    If you want to see the iframe just call: $fileWidget->enableDebug(); at the top of the page

  8. Ziplace

    He, that script must be very impressive but i can’t get it work :o(

    Thirst, the link demo without patch don’t work.

    Second, my version of PHP on my server is 4.3.8, if i understand, i don’t need this patch because it say:
    “Patch for php/sapi/apache2 (no longer needed since php-4.3.7 and php-5.0.0RC3)”

    And when i launch test.php i have this error:
    Fatal error: Call to undefined function: upload_progress_meter_get_info() in /home/httpd/vhosts/helpinfo.fr/subdomains/test/httpdocs/test.php on line 3

    It seems that i need something. Please help, i don’t want to put some CGI on my server, this script is very good for me!

  9. Joshua Eichorn Post author

    Ziplace: I’m pretty sure you need the patch, but even if you didn’t you would still need to compile the upload progress meter extension.

    test.php is trying to run the extension code (what you really want to run is demo.php) getting that error means you don’t have the extension working correctly.

    The link to the second demo is fixed now

  10. Michiel

    Hi there.

    Great script!
    worked fine.. but somtimes the upload bar jumped to the end at the start. And when i tryed the script few days later. It only jumps to the end..so the bar doesn’t work anymore. Is it a common problem?

    Thnx for the help

  11. Joshua Eichorn Post author

    Michiel: Well if the extension isn’t working right on the server you won’t get real feedback and I did upgrade my server yesterday.

    I’m not sure what your running into besides that.

  12. Michiel

    I installed the patch and extension under debian.
    Then i tested the demo with the extension en it worked.

    Then i have tested you’re demo. It worked to. But suddenly after a few days it doesn’t work anymore.

    It’s a weird problem. The error says that there is no file uploaded.

    Im sure i have the file size set good.

    maybe it doens’t work cause i first had the old version installed with the patch and extension? ( the download was al little bit blury )

    Maybe its a good idee to reinstall the patch en extenstion? Good you give me a good link to the latest versions?

    When the script worked before i liked it very much. So i wanna get it working again 🙂

    thnx already!

  13. Michiel

    Dear Joshua,

    I found the problem. The uploadbar directory i created in /tmp was automatically deleted.( i guess by a running script) once i created the dir, the script worked. Now i’m gone see if i can config the tmp dir to some other dir.

  14. Michiel

    i have a tip for multiple upload boxes. You kan place them with the function render() but the names will remain the same. If you change the function that you can give a name, like i did. render($name) an place that in the name AND submitname. Then the upload boxes can have different names. ofcourse let the function check if a default name is filled in in the global vars of the class.

  15. Mark

    Hi Josh,

    First off, fantastic work. I came across your project when I was looking for this exact solution, and it’s very impressive. So I ran into a very interesting problem when attempting to use the bar recently (I’ve built a version into my own form and it works nicely on my personal server). While it works fine on my personal server, the problem came when I attempted to transport everything to an off-site server. The off site hosting company is not without its quirks. First off, it’s a shared server. Each homepage gets its own folder etc etc… I had to set up a local configuration for PEAR, then I installed HTML_AJAX. I then basically mirrored what I have on my personal server. Here’s where the problem comes. The page that uses the status bar misses something, and the bar never shows an “In Progress” status. It stays on the “Connecting” status, never animates, then shows a full bar when done. It’s strange because it must be including the file (no error), the PEAR modules work (I installed the HTTP module and did a redirect to test), so I was hoping you’d have an idea of where to go from here. Thanks.

  16. Joshua Eichorn Post author

    Mark:
    Are you using it on your local install without the patch. Also are you seeing any JavaScript errors when things fail on the server, also can you mail me the url so I can take a look.

  17. Mark

    Josh–

    Both installs are without the patch. I e-mailed links to both the working and non-working sites. There aren’t any errors, but I’m guessing you can probably just look at it and tell me that it’s not getting something. I appreciate your help. Thanks.

  18. Matt

    I’ve got the demo working on my local apache webserver, but when I try to apply this ajax upload to my application, I get a blank screen that consists of:

    array(0) { }

    Has anyone else run into this problem? I’ve fixed all of the src paths and placed the correct PHP/JS code in the right spots, as far as I can tell…

    Thanks

  19. Matt

    Oh, nevermind!

    My problem was that my file upload was inside of a pre-existing . Whoops.

  20. Matt

    Argh, my previous post had some html tags in it. It should read:

    My problem was that my file upload form was inside of a pre-existing form.

  21. quba

    It works on my localhost, but there: http://mforum.ert.pl/trunk/demo.php
    it doesn’t work. Why ? When I use apache – it works. When I use lighttpd – id doesn’t work.
    Requirements: If you want to use the code you need to:
    Install HTML_AJAX (pear install HTML_AJAX-alpha)
    Download PAFUPMU and install it somewhere accessible.
    Add the code to your page using demo.php as an example.

    🙁

  22. Joshua Eichorn Post author

    lighttpd must not be setting $_SERVER[‘REQUEST_METHOD’], maybe it sets something else.

    UploadProgressMeter.class.php line 62. Let me know if you find a workaround, maybe just check for _POST having a count > 0

  23. Toby

    I can run the demo on your website on Opera. When I install it on my webserver I can only run it with IE but not Opera.

    [Server_Error] Statement on line 853: Syntax error in call to eval: line 1 :

  24. Joshua Eichorn Post author

    The patch is required on newer versions of PHP. It looks like the link too it got removed so im not sure what the next step is.

    I’ll be looking for an altenate solution, hopefully one that isn’t a perl cgi script.

    Feel free to email me, and i’ll dig around for a copy of the patch, im sure i have one on my server.

  25. buddyrandom

    what’s the point of the patch ? why doesn’t the function which polls every 2 seconds just read the current filesize of the tmp_file and calculate based on that. if it’s a matter of passing data back to the app, have the submit button for the upload trigger a javascript function which, after a second or so delay, reads a .data file created by the upload receiving function with pertinent details.

  26. Joshua Eichorn Post author

    Buddyrandom:
    The patch gives you access to the status of the upload. Your polling so that you can show the current speed, and how much has been uploaded.

    The point is too support big file uploads that take minutes not seconds.

  27. Pingback: <Erase una vez… » Códigos para subir archivos desde http

  28. Pingback: Dreaming of Dawn » Blog Archive » Finally! File Upload Progress for php (5.2)

  29. saran

    congrats!this is most needed script ever. unfortunatelly, I could not get it working. Could you post step by step instructions along with the links of resources. The site with patches does not seem working. How do I install the patch and does it work under iis win2003 server?

  30. Michiel

    Joshua,

    I want to use the script without the patch.
    So with a animated upload bar.

    But i’m getting this JS error.
    UploadProgressMeterStatus not defined.

    Could you tell me how to fix this?

    Greetz,

    Michiel

  31. Michiel

    I fixed the above error.

    But now i get the following JS error: “HTML_AJAX undefined”

    What must i do to solve it?

    Greetz,

    Michiel

  32. campos

    Hi, ive been tryin to get this progress meter working for a couple of days now (the basic one, without the HTML_AJAX stuff), i tried 3 different php versions (4.3.10, 4.3.7 and 4.4) – all with apache2

    i even updated my 4.3.7 to 4.3.10 (applied the patch, reconfigured and recompiled php) as it looked to me like it would refuse to work… still i wasn’t able to get it working… the php_values which i set in the httpd.conf (tried it in the php.ini aswell, same result) are ignored, and the progress meter extension doesnt show up in the phpinfo.php, so it seems like it doesnt work -and well when i try to use the extension it gives me an error sayin: Fatal error: Call to undefined function: upload_progress_meter_get_info() in /srv/www/vhosts/ … /httpdocs/upload/live-demo/progress.php on line 14

    extension dir is set to the the right value
    all steps i went through as written down at the site,

    all the steps went without any error/warning but it still refuse to work 😮

    help would be highly appreciated, if you have any hints for me, either post here or contact me campos AT gmx DOT at

    (or msn storm_cam AT hotmail DOT com)

  33. Joshua Eichorn Post author

    If anyone is having compile problems i would really recomend looking at php 5.2 it has a slightly different upgrade progress system built in.

  34. Dang

    Hi Joshua,

    I have error: ‘UploadProgressMeterStatus’ is undefined

    Could you show me how to fix it?

    Thanks

  35. Greg

    Hi Joshua,

    I can’t seem to figure out what “HTML_AJAX is undefined” means. Could you provide some assistnace?

    Thanks!

    Greg

  36. ryoku

    Great script, I installed it on my website thanks a lot.
    But I had few problems…

    1. I spent hours while trying to install the patch… In the README file it’s written upload_progress_tracking.so, but the file is actually named
    upload_progress_meter.so
    (when you’re a noob like me it takes time to notice that…)

    2. The JS errors
    When uncompressing the “HTML_AJAX-0.2.5-dev.tgz” archive, it will create a directory named “HTML_AJAX-0.2.5”, you need to rename it to “HTML”.
    Edit the file “HTML/AJAX/Server.php” at line 64 change
    var $clientJsLocation = false;
    to
    var $clientJsLocation = “HTML/js/”;

    3. I wanted to put all the files of the script into a subdirectory except “demo.php”. If you try this, you’ll need to change all the path of this file +
    the path of the “UploadProgressMeter.js” in the “UploadProgressMeter.class.php” file.

    And finally the script works (after hours and hours xD) ^^

  37. Joshua Eichorn Post author

    ryoku: just install HTML_AJAX from pear, 0.5.0 should work fine for you

    Also php 5.2 has upload progress tracking built in so the days of patching things are soon over

  38. Greg

    Hey Joshua,

    Any advice on my problem with the “HTML_AJAX is undefined”?

    Thanks,

    Greg

  39. Tore Krudtaa

    To Joshua Eichorn.

    I have tested the new upload features in PHP 5.2
    This looks cool, but requires APC extension to work, AFAIK.

    Do you know if it is possible to use the upload progress tracking in PHP 5.2 without the APC extension?

    If you know, please describe how to do it.