3
Dec/08
56

Creating an Upload Progress Bar in PHP with APC

  1. Introduction
  2. Create the Form
  3. The PHP Scripts
  4. The JavaScript (AJAX)
  5. The Finished Product
  6. View All

Introduction

In this tutorial I will explain how to create a progress bar for PHP file uploads. There is no method built into PHP for returning the status of an upload in progress, so this requires a module called the Alternative PHP Cache (APC). This allows you to store data across sessions and includes built-in functionality for storing/returning file upload stats.

This tutorial assumes you have some basic understanding of XHTML, PHP, and JavaScript. If you don't, it may be hard to understand.

Installing APC is beyond the scope of this tutorial, so visit the APC Installation page for help or talk to your host. To find out if APC is installed already, create a PHP file on your site containing "<?php phpinfo(); ?>", visit it in your browser, and look for a section titled 'APC.' If it is present, then it is installed.

Similar Posts:

 

« Previous  Next »

Author: Steve

Steve is the owner of UlraMega Tech. He is a freelance Web designer and developer who specializes in PHP and AJAX development.
Comments (56) Trackbacks (1)
  1. Hello,
    this the best tutorial about APC upload I have ever seen. Unfortunately, it doesn’t work to me. When I upload file, apc almost immediately return {finish:true;}, therefore file isn’t uploaded yet. I have read about this problem (bug) something, but it is explained very well nowhere. Do you have survey in which cases (server configuration) it happens?
    Thank you a lot.

    tomasr

  2. Hello,
    this upload bar is excellently working in FF, but I have noticed, that in IE (both 6 and7) it doesn’t work. It just returns error, that object was expected @ line XY (I think it is line with , but it is in IE, so who knows…)
    Do you know what I (if it is me) am doing wrong?

    Jen

    • Actually this was an error on my part. When including the script on the page, the type should be text/javascript not application/javascript. I’ve corrected the tutorial to reflect that.

      Sorry for the confusion

  3. Yes I’m sure that I’ve apc.rfc1867 = On in php.ini on localhost and production server as well.
    I don’t know why it doesn’t work on localhost. Only one reason, why it doesn’t work on production servver is that php is there compiled like fastcgi and I’ve ever read, that in this case apc doesn’t work.

    Any idea?

    • I can’t find any information on any configuration that would cause that. It’s probably something in your script.

  4. http://www.ibm.com/developerworks/opensource/library/os-php-v525/index.html

    IBM recommends “Using a text editor, open /php/php.ini and add the line apc.rfc1867 = on (it doesn’t matter where). If you’re trying to test locally and plan to upload large files so you can actually see progress, you’ll also want to add the following directives: apc.max_file_size = 200M, upload_max_filesize = 200M, and post_max_size = 200M. Don’t do this on a live production server, though, or you’re likely to use up bandwidth and disk space allotments, not to mention slowing everyone else down to a crawl.” <- WAMP

    for localhost tests. I dont know if this will help or not.

  5. I am completely lsot this about about the most amazing tutorial I have ever seen yet for some reason i cannot get it working.

    I want to use this script for uploading videos to a website i am building but cant get a local demo running for the life of me!!!!

    Any Ideas????

    http://fadetoclear.com/uploader/upload_form.php

  6. hi!
    it works with multiple uploads?
    i would like to upload 3 files at time.

  7. Thanks for a very useful tutorial. I truly appreciate it.

    In case this will help others in the future. I had to change
    from $_FILES['userfile']['name'] to $_FILES['file']['name']
    and from $_FILES['userfile']['tmp_name'] to $_FILES['file']['tmp_name']
    in order for the code to work.

  8. Thanks for the tutorial. Works excellent!!!!

    How do i make the progress bar uploading to be done in a separate window? and when i try uploading files of larger size i get a division by zero warning and the progress bar stops working. Could you please help me out with these two issues.

    • I think the easiest way to use a separate window is to load the upload form in a separate window, and it should work just fine. Otherwise, you can add some JavaScript to the startProgress function to pop open a new window.

      The division by zero can be caused by a number of things. Maybe your PHP configuration has the apc.max_file_size, upload_max_filesize, or post_max_size set too low to allow your large files.

  9. Hi

    I am using above exaple but in my code apc_fetch function is not working.
    php.ini file setting is as below:

    apc.enable_cli Off Off
    apc.enabled On On
    apc.file_update_protection 2 2
    apc.filters no value no value
    apc.gc_ttl 3600 3600
    apc.include_once_override Off Off
    apc.max_file_size 40M 40M
    apc.mmap_file_mask no value no value
    apc.num_files_hint 1000 1000
    apc.report_autofilter Off Off
    apc.rfc1867 On On
    apc.rfc1867_freq 0 0
    apc.rfc1867_name APC_UPLOAD_PROGRESS APC_UPLOAD_PROGRESS
    apc.rfc1867_prefix upload_ upload_
    apc.shm_segments 1 1
    apc.shm_size 30 30
    apc.slam_defense 0 0
    apc.stat On On
    apc.stat_ctime Off Off
    apc.ttl 0 0
    apc.user_entries_hint 4096 4096
    apc.user_ttl 0 0

    Please help me to sort out this.I think $status['total'] is not working. Guide me what changes I have to do?

    • What version of PHP are you using? The upload tracking requires that APC is compiled against 5.2 or later. Other than that, I don’t see anything wrong with that configuration.

  10. No matter what I do, I cannot get apc to work. It is sooo troublesome. Im very frustrated. I set that rfc on, and enabled apc. yet, it isn’t working. What happens is when I upload a file, the file gets uploaded, but the stat doesnt change. the progress bar doesnt load, and it says “upload complete”.
    This is what my phpinfo says:

    apc
    APC Support enabled
    Version 3.0.19
    MMAP Support Enabled
    MMAP File Mask no value
    Locking type pthread mutex Locks
    Revision $Revision: 3.154.2.5 $
    Build Date Aug 15 2009 09:40:40

    Directive Local Value Master Value
    apc.cache_by_default On On
    apc.coredump_unmap Off Off
    apc.enable_cli Off Off
    apc.enabled On On
    apc.file_update_protection 2 2
    apc.filters no value no value
    apc.gc_ttl 3600 3600
    apc.include_once_override Off Off
    apc.max_file_size 10M 10M
    apc.mmap_file_mask no value no value
    apc.num_files_hint 1000 1000
    apc.report_autofilter Off Off
    apc.rfc1867 On On
    apc.rfc1867_freq 0 0
    apc.rfc1867_name APC_UPLOAD_PROGRESS APC_UPLOAD_PROGRESS
    apc.rfc1867_prefix upload_ upload_
    apc.shm_segments 1 1
    apc.shm_size 30 30
    apc.slam_defense 0 0
    apc.stat On On
    apc.stat_ctime Off Off
    apc.ttl 0 0
    apc.user_entries_hint 4096 4096
    apc.user_ttl 0 0
    apc.write_lock On On

    PLEEEASE HELP ME! what am I doing wrong?

  11. code is not working. apc is enable but
    when I upload a file, the file gets uploaded, but the stat doesnt change. the progress bar doesnt load, and it says “upload complete”.Please help me. apc configuration is as follows

    pc.cache_by_default On On
    apc.coredump_unmap Off Off
    apc.enable_cli On On
    apc.enabled On On
    apc.file_update_protection 2 2
    apc.filters no value no value
    apc.gc_ttl 3600 3600
    apc.include_once_override Off Off
    apc.max_file_size 40M 40M
    apc.mmap_file_mask /tmp/apc.gkjMYq /tmp/apc.gkjMYq
    apc.num_files_hint 1024 1024
    apc.report_autofilter Off Off
    apc.rfc1867 On On
    apc.rfc1867_freq 0 0
    apc.rfc1867_name APC_UPLOAD_PROGRESS APC_UPLOAD_PROGRESS
    apc.rfc1867_prefix upload_ upload_
    apc.shm_segments 1 1
    apc.shm_size 128M 128M
    apc.slam_defense 0 0
    apc.stat On On
    apc.stat_ctime Off Off
    apc.ttl 7200 7200
    apc.user_entries_hint 4096 4096
    apc.user_ttl 7200 7200
    apc.write_lock On On

  12. Code is not working . when I upload a file, the file gets uploaded, but the stat doesnt change. the progress bar doesnt load, and it says “upload complete”.Please help me. apc configuration is as follows

    pc.cache_by_default On On
    apc.coredump_unmap Off Off
    apc.enable_cli On On
    apc.enabled On On
    apc.file_update_protection 2 2
    apc.filters no value no value
    apc.gc_ttl 3600 3600
    apc.include_once_override Off Off
    apc.max_file_size 40M 40M
    apc.mmap_file_mask /tmp/apc.gkjMYq /tmp/apc.gkjMYq
    apc.num_files_hint 1024 1024
    apc.report_autofilter Off Off
    apc.rfc1867 On On
    apc.rfc1867_freq 0 0
    apc.rfc1867_name APC_UPLOAD_PROGRESS APC_UPLOAD_PROGRESS
    apc.rfc1867_prefix upload_ upload_
    apc.shm_segments 1 1
    apc.shm_size 128M 128M
    apc.slam_defense 0 0
    apc.stat On On
    apc.stat_ctime Off Off
    apc.ttl 7200 7200
    apc.user_entries_hint 4096 4096
    apc.user_ttl 7200 7200
    apc.write_lock On On

  13. APC installation and configuration are beyond the scope of this tutorial. You may want to look at the uploadprogress PECL extension (http://pecl.php.net/package/uploadprogress) as an alternative to APC.

  14. Thank you so much for this script i m using IIS 6 and php 5.2 on win xp sp3
    I ve tried so many scripts to show progress bar but i ve failed until use your script.It s working and showing bar and % without any problem.One minor problem is about ff.First it shows the bar and progress but when i refresh it doesn t show anything.I think it s about cache.When i closed and open again ff, it shows bar first time but doesn t show anythinh second time.Any idea?

    Note: i ve used php as a Cgi then i changed it to Isapi today,now everything is fine.

  15. one more thing that i ve realised just know is the uploaded data isnt send to upload.php
    Apc functions and progress bar works correctly,probably uploaded data is send to temporary folder,any idea about why doesn t uploaded data sent to upload.php?

  16. i changed $path .= basename($_FILES['file']['name']); to
    $path =$path.basename($_FILES['file']['name']);
    ——-
    $path = ‘temp/’;
    $path =$path.basename($_FILES['file']['name']);
    if(move_uploaded_file($_FILES['file']['tmp_name'], $path)){
    and added echo ““.$path.”“.
    ” succes”;
    echo “$target_path“;

    }

    else{
    echo “Dosya göndeilemedi!”;
    }

    now uploaded data is sent to upload.php and file save to folder which is referred to “temp/ ” inside upload.php.

    but if the file bigger than 15mb the upload bar instantly goes to %100

    post_max=200m
    upload_size=200m
    apc.max_file_size=200m

  17. Hi I’m hoping that someone can help me out. When I goto info.php there is a APC section that currently has apc.rfc1867 set to OFF and apc.max_file_size is set to 1M apc.enabled is set to ON.

    This is the location to where the php.ini file is located: /etc/php5/apache2/php.ini

    The problem is when I open php.ini to edit it, there is mention to ( apc) at all.

    Can anyone help me?

    Thank you.

  18. Thank you Steve for such a great script and for your help.

    I recently downloaded Ubuntu 9.04 cause I didn’t like the new Mandriva version, and I decided to use it as a server so friends can connect to me and download and upload files. The problem was when they uploaded something There Progress Bar would be at 100% while the upload wasn’t finished yet.

    So I went on a search for a .php upload with progress bar and ended up here.

    Thank you once again. and for your quick fix reply.

  19. hey steve i have last one question.When i upload a file that bigger than 20mb,bar goes to %100 instantly,but upload s still going then it finish without any problem here is my php.ini.I m using IE 7 and IIS 6.Is is about IIS or apc configs?

    post_max=200m
    upload_size=200m
    apc.max_file_size=200m
    apc.rfc1867 = on
    apc.enabled=1

  20. i solved it.Who want to send files about 100M need to set :
    function startProgress(uid)
    ………..
    setTimeout(‘getProgress(“‘ + uid + ‘”)’, 1000);

    1000(ms) to 3000-8000 (ms).

    I think it s depends on how many ram the server machine have.

  21. Hi Steve.
    This is a great tutorial so far I found on website, thanks. One problem I have is that
    I installed APC and configured everything, when i upload file, the progress bar just show 100% complete on FF browser. I first thought of the upload file size is too small than I changed to large file size but it still showed the same. I then put an alert message in the Ajax function to check the “progress” returned from responsetext, it shows the 100% only once. Where could be the problem?
    Thank you,

    • Try increasing the timeout in the startProgress JS function. It worked for the previous poster.

      function startProgress(uid) {
         document.getElementById('upload').style.display = 'none';
         document.getElementById('pb_outer').style.display = 'block';
         setTimeout('getProgress("' + uid + '")', 3000);
      }

      Let me know if it works so I can update the tutorial.

      • Thanks for reply – it didn’t work for me. The progress bar doesn’t show percentage of completion, it only shows “Upload Complete” at the end. File is uploaded to a temp directory. I will double check the ajax part.

        • I think I might find the problem by putting debug message in the ajax code in the request object status and responseText, and hardcode a return value in getprogress.php, then the percentage showed, and the setTimeout triggered. It seems like the return value always be 100 from getprogress.php, and that is I was getting the “Upload Complete” all the time, why is it? Could it related to cache problem? I did put the header expire code in it like the sample code.

          • if you use php-cgi ,you should change it to isapi,it is known that php-cgi has a problem with apc extension.

  22. Thank you for reply – but how to change to isapi exactly? thanks

  23. do you use IIS or apache as a web server?

  24. Hey steve,how can i show to user uploaded file name and total file size when progress bar seems on screen?

    • In getprogress.php, $status contains an array of file information. $status['total'] is the file size in bytes, and $status['filename'] is the name of the file. Other values are current (bytes uploaded), rate (upload speed B/s), name (variable name), temp_filename (temporary file location), cancel_upload (1 if upload is cancelled), done (1 if upload is complete).

      Basically, you can have getprogress.php return some JSON and parse the different values within JavaScript. You can simply return the whole array like this:

      if(isset($_GET['uid'])){
         $status = apc_fetch('upload_' . $_GET['uid']);
         echo json_encode($status);
      }

      Then your JavaScript for getProgress() will look something like this:

      if(HttpRequestObject.readyState == 4 && HttpRequestObject.status == 200) {
         var progress = eval('('+HttpRequestObject.responseText+')');
         var percent = Math.round(progress.current/progress.total*100);
         document.getElementById('pb_inner').style.width = percent + '%';
         document.getElementById('pb_inner').innerHTML = percent + '%';
         if(progress.done == 0) {
            setTimeout('getProgress("' + uid + '")', 100);
         }
         else {
            document.getElementById('pb_inner').innerHTML = 'Upload Complete!';
         }
      }

      That should give you the same result as before, but now you can access all the pieces of data about the file from the progress object. So you can insert the value of progress.total, progress.filename, or even progress.rate anywhere on the page.

      Hope this helps!

  25. Hey Steve I’m sorry to bother you further but I was wondering based on that example site, Is it possible to display an estimate time for download that will refresh it’s figures appropriately?

    • It seems like the transfer rate only appears when the upload is complete, so I don’t know if that’s possible unfortunately. Otherwise you would divide the filesize (subtract current if you want time remaining) by the rate to get the number of seconds.

  26. sorry but I’m really new to .php

    would that be:

    var progress = eval(‘(‘+HttpRequestObject.responseText+’)');
    var percent = Math.round(progress.current/progress.total*100);

    + var TimeRemaning = Math.round(progress.total/progress.current); +

    document.getElementById(‘filename’).innerHTML = progress.filename;
    document.getElementById(‘filesize’).innerHTML = progress.total;
    document.getElementById(‘current’).innerHTML = progress.current

    + document.getElementByld(‘TimeRemaning’).innerHTML = progress.TimeRemaining +

    I really kind of feel bad to bother you, but I guess you had to expect morons like me to come along and wish you never bothered to post such a fine script to begin with.

    :)

    • Assuming you have access to the rate value during upload, you would get the number of seconds remaining with:

      var remaining = Math.round((progress.total-progress.current)/progress.rate);
      document.getElementById('remaining').innerHTML = remaiining;
      <p>Time Remaining: <span id="remaining"></span> sec.</p>

      Anyway, this relies on APC to return the transfer rate during upload. Otherwise you’ll have to figure out a way to estimate the rate within JavaScript.

  27. document.getElementById(‘remain’).innerHTML = (progress.total/progress.current);

    and add

    …..

    Remain: sec

  28. i got installation problem in APC.After i installed and put extension=”apc.so”. in php.ini it shows following error

    Warning: PHP Startup: It is not safe to rely on the system’s timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected ‘America/Halifax’ for ‘-4.0/no DST’ instead in Unknown on line 0

    but i mentioned timezone in php.ini,any one can help me

  29. Great tutorial! Its exactly what I need. Unfortunately I’m stuck and cant seem to figure out the problem. First I tried a 1.3 Mb file which worked fine but since I am doing it all locally, the bar immediately went to 100%. Then I tried a larger file (around 10 Mb) but the bar never makes any progress and instead displays “Upload Complete” with Upload inside the left side of the bar and Complete underneath the bar.

    phpinfo() shows apc installed with rfc1867 and max file size of 200M. I also made sure isapi_module was selected in Apache on wamp. Can anyone help me out?

    • function startProgress(uid)
      ………..
      setTimeout(’getProgress(”‘ + uid + ‘”)’, 1000);

      change 1000(ms) to 3000-8000 (ms).

      try this.

  30. hey steve,do know any host that i can install and use apc extension?

    • Sorry, I don’t know of any hosts that allow that kind of access. You’ll need to find a host that has APC installed, get a VPS or server, or use another progress bar solution.

  31. Can it work with mod_security? If I enabled it, it don’t works, but in the mod_sec logs, I don’t see anything.

  32. Hi Steve,

    I really appreciate your tutorial and the example works fine on my local test server. Unfortunately the webmaster of our site decided only to allow access to any page using “index.php?site=webpage” where the target file is located in a subfolder like “/webpage/webpage.php”. While the upload still works for itself, no information about the progress is received. I reckon it’s because of the following code line:

    HttpRequestObject.open(‘GET’, ‘index.php?site=getprogress&uid=’ + uid, true);

    Is there any way to include getprogress.php into upload_form.php? In case not, how can the uid be passed to getprogress.php properly?

  33. let progress bar work -

    <input type="hidden"

    must be BEFORE

    <input type="file"

Leave a comment


Page optimized by WP Minify WordPress Plugin