Creating an Upload Progress Bar in PHP with APC
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.
Creating the HTML Form
The first step is to create the form that will accept the file upload. This page will also contain the progress bar, hidden when the page loads. Start with creating the <form> element:
1 2 3 4 5 6 7 8 9 10 11 12 | <html> <head> <title>Upload Progress Bar</title> </head> <body> <form action="upload.php" method="post" enctype="multipart/form-data" name="upload" id="upload" target="upload_frame"> <input type="hidden" name="APC_UPLOAD_PROGRESS" id="progress_key" value="<?php echo $uid; ?>" /> <input type="file" name="file" id="file" /> <input type="submit" name="submit" id="submit" value="Upload!" /> </form> </body> </html> |
Save this file as upload_form.php.
Now to break down the code:
6 | <form action="upload.php" method="post" enctype="multipart/form-data" name="upload" id="upload" target="upload_frame"> |
The important thing that allows a form to accept files is the enctype="multipart/form-data" attribute, which allows binary data (files). The action is set to the script that will accept the file, target is set to a hidden iframe that we will add, and id is set so we can access the form with JavaScript.
7 | <input type="hidden" name="APC_UPLOAD_PROGRESS" id="progress_key" value="<?php echo $uid; ?>" /> |
This part tells APC to record the upload stats from this form. The value will be a unique string generated by PHP used to identify the upload session.
The next two lines are the file selector and submit button and are fairly self-explanatory.
Next, we need to add the progress bar. The bar will consist of two CSS-styled divs, one nested within the other. The inner one will expand based on the upload progress. Here is what it looks like:
<div id="pb_outer"> <div id="pb_inner"></div> </div>
Here is some good CSS to style the progress bar. Place this within the head tags:
<style type="text/css"> #pb_outer { height: 20px; border: 1px inset #000000; width: 80%; margin: 20px auto; display: none; } #pb_inner { font-weight: bold; color: #FFFFFF; background-color: #003399; height: 20px; width: 1px; text-align: center; } </style>
This sets the size (80% width, 20px height), position (centered), colors (blue bar with white text), and makes it all hidden initially. You can easily change the style by just editing this CSS block.
Now is also a good time to add that hidden iframe that will upload the file in the background:
<iframe style="display: none" id="upload_frame" name="upload_frame"></iframe>Here is what upload_form.php should look like now:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <html> <head> <title>Upload Progess Bar</title> <style type="text/css"> #pb_outer { height: 20px; border: 1px inset #000000; width: 80%; margin: 20px auto; display: none; } #pb_inner { font-weight: bold; color: #FFFFFF; background-color: #003399; height: 16px; width: 1px; text-align: center; padding: 2px 0px; } </style> </head> <body> <form action="upload.php" method="post" enctype="multipart/form-data" name="upload" id="upload" target="upload_frame"> <input type="hidden" name="APC_UPLOAD_PROGRESS" id="progress_key" value="<?php echo $uid; ?>" /> <input type="file" name="file" id="file" /> <input type="submit" name="submit" id="submit" value="Upload!" /> </form> <div id="pb_outer"> <div id="pb_inner"></div> </div> <iframe style="display: none" id="upload_frame" name="upload_frame"></iframe> </body> </html> |
Creating the PHP Scripts
Now that we have a form that submits a file to a non-existent PHP script via a frame, it's time to make that script (and some helper scripts).
First, we need to generate that unique key with just one simple line in upload_form.php:
<?php $uid = md5(uniqid(rand())); ?>
Place this line at the very top of upload_form.php. This creates a random unique id (uniqid()) and hashes it with md5 to make sure it is URL safe. When the page loads, "APC_UPLOAD_PROGRESS" will have a value set to this string.
Now it's time for an actual file upload script, which generally looks like this:
1 2 3 4 5 6 7 8 9 | <?php if($_FILES['file']['error'] == UPLOAD_ERR_OK){ $path = '/var/www/uploads/'; $path .= basename($_FILES['file']['name']); if(move_uploaded_file($_FILES['file']['tmp_name'], $path)){ // upload successful } } ?> |
Note: On PHP versions prior to 4.1.0 replace $_FILES with $HTTP_POST_FILES
Place this code in a file called upload.php. This will make sure there was no upload error, and then move the file to the specified path. Note that if you do not use move_uploaded_file(), the uploaded file will be deleted from the temp directory.
The last bit of PHP we need is for fetching the current upload progress:
1 2 3 4 5 6 | <?php if(isset($_GET['uid'])){ $status = apc_fetch('upload_' . $_GET['uid']); echo round($status['current']/$status['total']*100); } ?> |
Place this in a file named getprogress.php. This fetches an array of upload stats from APC using the unique id with the "upload_" prefix (this will be passed via a GET variable). Then it calculates the uploaded percentage by dividing the current position ($status['current']) by the total size ($status['total']) and multiplying by 100. The script will return this number rounded to the nearest whole number.
There is one slight problem with this script, especially since we will be calling this with AJAX, and that is caching. Some browsers will cache the output of the script and cause the bar to freeze after the initial request. To solve this, we can use headers to instruct the browser not to cache:
2 3 | header('Expires: Tue, 08 Oct 1991 00:00:00 GMT'); header('Cache-Control: no-cache, must-revalidate'); |
The first header tricks the browser into thinking this is a very old document that expired in 1991, and the second is the standard cache control settings. Both are needed in case the browser ignores the Cache-Control header.
Here is what getprogress.php should look like:
1 2 3 4 5 6 7 8 9 | <?php header('Expires: Tue, 08 Oct 1991 00:00:00 GMT'); header('Cache-Control: no-cache, must-revalidate'); if(isset($_GET['uid'])){ $status = apc_fetch('upload_' . $_GET['uid']); echo round($status['current']/$status['total']*100); } ?> |
Creating the JavaScript (AJAX)
Now this is where it gets interesting. We need to uses JavaScript to animate the progress bar based on the output of getprogress.php, and this requires the use of AJAX. AJAX is a method that allows you to load content on demand without reloading the entire web page.
To set up the AJAX functionality, we need to create a cross-browser request object. There are two main types of request objects, one that works on most browsers, and one that works in Internet Explorer. Below is the code that I use to handle this. Place this within the head tags in upload_form.php:
1 2 3 4 5 6 7 8 9 | <script type="text/javascript"> var HttpRequestObject = false; if(window.XMLHttpRequest) { HttpRequestObject = new XMLHttpRequest(); } else if(window.ActiveXObject) { HttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP"); } </script> |
This creates an object named HttpRequestObject, which holds whichever AJAX object is available in the user's browser. The first condition checks for the existence of the XMLHttpRequest object (Firefox, etc.), and if that fails it will check for the equivalent ActiveXObject (Internet Explorer). You may also want to add error handling in case neither one is available.
Now that we have that set up, we need the actual functions that do the work. We will create two functions, one that initializes the progress bar and one that moves the progress bar. We will start with the one that moves the bar and makes the AJAX calls. Let's start with the backbones of using AJAX:
1 2 3 4 5 6 7 8 9 10 | function getProgress(uid) { if(HttpRequestObject) { HttpRequestObject.open('GET', 'getprogress.php?uid=' + uid, true); HttpRequestObject.onreadystatechange = function() { if(HttpRequestObject.readyState == 4 && HttpRequestObject.status == 200) { } } HttpRequestObject.send(null); } } |
This creates the function getProgress(), which has the unique ID passed to it as an argument. First it checks if the HttpRequestObject exists before trying to use it. Then using that, it uses the open method to set up the request. The open method accepts 3 arguments: the request method, the URL, and whether the request is asynchronous. The request method is GET in this case, but the other common method is POST which is slightly more complex. Asynchronous means that other actions (other AJAX calls) can take place while the request is being made; setting this to false will cause everything to pause until it is done, which might be useful in some situations.
Since we are using GET, we pass variables by appending it to the URL in the format ?key=value, in this case we pass the unique ID this way. The next part of the function uses the onreadystatechange event handler to set up the actions that will happen as soon as the data is returned. If the readystate is 4 (finished), and HTTP response code is 200, then it is ready to do stuff. The last line of the function is what actually sends the request to the server.
Now that we have out function set up to query the server for upload status, it is now time to use the info to move the progress bar. Here's the code we'll use:
6 7 8 | var progress = HttpRequestObject.responseText; document.getElementById('pb_inner').style.width = progress + '%'; document.getElementById('pb_inner').innerHTML = progress + '%'; |
This fetches the response as text using responseText and stores it in a variable called progress. The next line sets the width to the percentage using the style.width property, and the one after that sets the text inside of the bar to display the response using the innerHTML property.
At this point, the function will execute just once. We need to cause it to loop until the upload is complete. This can be easily accomplished using the setTimeout function, which calls a function after a delay set in milliseconds. In this case we'll call the getProgress() function again.
9 10 11 12 13 14 | if(progress < 100) { setTimeout('getProgress("' + uid + '")', 100); } else { document.getElementById('pb_inner').innerHTML = 'Upload Complete!'; } |
This will cause the function to call itself every 10th of a second as long as the percentage is below 100. If it is at 100, it will stop and set the text to say "Upload Complete."
Here is the function in it's entirety:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | function getProgress(uid) { if(HttpRequestObject) { HttpRequestObject.open('GET', 'getprogress.php?uid=' + uid, true); HttpRequestObject.onreadystatechange = function() { if(HttpRequestObject.readyState == 4 && HttpRequestObject.status == 200) { var progress = HttpRequestObject.responseText; document.getElementById('pb_inner').style.width = progress + '%'; document.getElementById('pb_inner').innerHTML = progress + '%'; if(progress < 100) { setTimeout('getProgress("' + uid + '")', 100); } else { document.getElementById('pb_inner').innerHTML = 'Upload Complete!'; } } } HttpRequestObject.send(null); } } |
Now it is time to make that other function that starts the whole process:
1 2 3 4 5 | function startProgress(uid) { document.getElementById('upload').style.display = 'none'; document.getElementById('pb_outer').style.display = 'block'; setTimeout('getProgress("' + uid + '")', 1000); } |
All this does is hides the form by setting style.display to 'none' and shows the progress bar by setting style.display to 'block.' Next, it calls the getProgress() function after 1 second, passing the unique ID along.
Now all that is left is to tie the form the the JavaScript by adding this to the form HTML element:
onSubmit="startProgress('<?php echo $uid; ?>');"The next page contains the completed code. Enjoy!
The Finished Product
I hope this was helpful! Any questions, post a comment. For your convenience, here is all the code used in this tutorial.
To see it in action, see our example.
upload_form.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | <?php $uid = md5(uniqid(rand())); ?>
<html>
<head>
<title>Upload Progess Bar</title>
<style type="text/css">
#pb_outer {
height: 20px;
border: 1px inset #000000;
width: 80%;
margin: 20px auto;
display: none;
}
#pb_inner {
font-weight: bold;
color: #FFFFFF;
background-color: #003399;
height: 20px;
width: 1px;
text-align: center;
}
</style>
<script type="text/javascript">
var HttpRequestObject = false;
if(window.XMLHttpRequest) {
HttpRequestObject = new XMLHttpRequest();
}
else if(window.ActiveXObject) {
HttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
}
function startProgress(uid) {
document.getElementById('upload').style.display = 'none';
document.getElementById('pb_outer').style.display = 'block';
setTimeout('getProgress("' + uid + '")', 1000);
}
function getProgress(uid) {
if(HttpRequestObject) {
HttpRequestObject.open('GET', 'getprogress.php?uid=' + uid, true);
HttpRequestObject.onreadystatechange = function() {
if(HttpRequestObject.readyState == 4 && HttpRequestObject.status == 200) {
var progress = HttpRequestObject.responseText;
document.getElementById('pb_inner').style.width = progress + '%';
document.getElementById('pb_inner').innerHTML = progress + '%';
if(progress < 100) {
setTimeout('getProgress("' + uid + '")', 100);
}
else {
document.getElementById('pb_inner').innerHTML = 'Upload Complete!';
}
}
}
HttpRequestObject.send(null);
}
}
</script>
</head>
<body>
<form onSubmit="startProgress('<?php echo $uid; ?>');" action="upload.php" method="post" enctype="multipart/form-data" name="upload" id="upload" target="upload_frame">
<input type="hidden" name="APC_UPLOAD_PROGRESS" id="progress_key" value="<?php echo $uid; ?>" />
<input type="file" name="file" id="file" />
<input type="submit" name="submit" id="submit" value="Upload!" />
</form>
<div id="pb_outer">
<div id="pb_inner"></div>
</div>
<iframe style="display: none" id="upload_frame" name="upload_frame"></iframe>
</body>
</html> |
upload.php
1 2 3 4 5 6 7 8 9 | <?php if($_FILES['file']['error'] == UPLOAD_ERR_OK){ $path = '/var/www/uploads/'; $path .= basename($_FILES['file']['name']); if(move_uploaded_file($_FILES['file']['tmp_name'], $path)){ // upload successful } } ?> |
getprogress.php
1 2 3 4 5 6 7 8 9 | <?php header('Expires: Tue, 08 Oct 1991 00:00:00 GMT'); header('Cache-Control: no-cache, must-revalidate'); if(isset($_GET['uid'])){ $status = apc_fetch('upload_' . $_GET['uid']); echo round($status['current']/$status['total']*100); } ?> |
Similar Posts:
- Saving Time With jQuery
- Toggle Display of Page Elements with JavaScript
- Add Records to a Queue with jQuery
About Steve
Steve is the owner of UltraMega Tech. He is a freelance Web designer and developer who specializes in PHP and AJAX development.Categories
- General (6)
- News (4)
- Projects (10)
- Lock My Stuff (2)
- TempServers (8)
- Software (7)
- Tips & Tutorials (45)
Archives
- [+]2010 (6)
- [+]2009 (46)
- [+]December (5)
- [+]November (3)
- [+]October (2)
- [+]September (4)
- [+]August (4)
- [+]July (4)
- [+]June (6)
- [+]May (4)
- [+]April (4)
- [+]March (4)
- [+]February (2)
- [+]January (4)
- [+]December (5)
- [+]2008 (15)
- [+]December (14)
- [+]November (1)
- [+]December (14)

February 9th, 2009 - 13:27
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
February 11th, 2009 - 12:51
Make sure you have this in your PHP configuration to enable upload tracking:
apc.rfc1867 = OnFebruary 13th, 2009 - 05:33
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
February 13th, 2009 - 11:08
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
February 21st, 2009 - 13:13
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?
February 23rd, 2009 - 21:29
I can’t find any information on any configuration that would cause that. It’s probably something in your script.
February 26th, 2009 - 08:00
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.
March 7th, 2009 - 01:37
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
March 9th, 2009 - 02:55
hi!
it works with multiple uploads?
i would like to upload 3 files at time.
March 9th, 2009 - 09:55
Yes, it should work fine with multiple files. Just add more files fields to the form and name them
file[]so PHP will treat them as an array. There is an example showing how to handle multiple files at: http://www.php.net/manual/function.move-uploaded-file.php#function.move-uploaded-file.examplesMarch 18th, 2009 - 07:32
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.
March 18th, 2009 - 11:06
Good catch! I corrected the tutorial. Copy/paste error…
June 29th, 2009 - 14:15
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.
July 27th, 2009 - 11:42
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.
July 27th, 2009 - 04:04
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?
July 27th, 2009 - 11:48
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.
August 17th, 2009 - 06:11
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?
April 27th, 2010 - 17:36
Make sure APC_MD5 is enabled
August 20th, 2009 - 05:35
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
August 20th, 2009 - 05:53
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
August 20th, 2009 - 14:21
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.
August 30th, 2009 - 23:35
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.
August 31st, 2009 - 03:02
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?
August 31st, 2009 - 05:27
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
August 31st, 2009 - 15:18
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.
August 31st, 2009 - 16:00
Just add this somewhere in the fle:
[apc]apc.rfc1867 = On
August 31st, 2009 - 16:47
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.
August 31st, 2009 - 22:33
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
September 1st, 2009 - 04:22
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.
September 2nd, 2009 - 13:42
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,
September 2nd, 2009 - 13:53
Try increasing the timeout in the startProgress JS function. It worked for the previous poster.
Let me know if it works so I can update the tutorial.
September 2nd, 2009 - 18:30
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.
September 2nd, 2009 - 18:57
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.
September 2nd, 2009 - 21:51
if you use php-cgi ,you should change it to isapi,it is known that php-cgi has a problem with apc extension.
September 3rd, 2009 - 05:30
Thank you for reply – but how to change to isapi exactly? thanks
September 3rd, 2009 - 09:46
do you use IIS or apache as a web server?
September 3rd, 2009 - 10:20
I am using Apache 2.0.63.
September 3rd, 2009 - 22:05
here is how to use mod_isapi for apache
http://httpd.apache.org/docs/2.0/mod/mod_isapi.html.
You should also set apc configuration in php.ini.
Try big files about 100-110mb.
I use this code on windows xp sp3-IIS 5.1 machine and Windows 7-Apache installed machine.Both work.
September 3rd, 2009 - 23:23
Hey steve,how can i show to user uploaded file name and total file size when progress bar seems on screen?
September 4th, 2009 - 09:44
In getprogress.php,
$statuscontains 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:
Then your JavaScript for getProgress() will look something like this:
That should give you the same result as before, but now you can access all the pieces of data about the file from the
progressobject. So you can insert the value ofprogress.total,progress.filename, or evenprogress.rateanywhere on the page.Hope this helps!
September 5th, 2009 - 00:12
Sorry, but after change all this, progress bar doesn t move.
September 5th, 2009 - 10:31
Here is a working example you can look at: http://www.ultramegatech.com/blog/examples/pb2/upload_form.php Just look at the source to see how it works. Also note that json_encode is available on PHP 5.2+. Otherwise you’ll need to manually produce the JSON.
I also added rounding for the percentage so you get an even number.
September 5th, 2009 - 12:32
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?
September 5th, 2009 - 14:14
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.
September 6th, 2009 - 00:07
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.
September 6th, 2009 - 10:58
Assuming you have access to the rate value during upload, you would get the number of seconds remaining with:
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.
September 6th, 2009 - 02:50
document.getElementById(‘remain’).innerHTML = (progress.total/progress.current);
and add
…..
Remain: sec
September 9th, 2009 - 05:12
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
September 14th, 2009 - 11:26
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?
September 14th, 2009 - 23:03
function startProgress(uid)
………..
setTimeout(’getProgress(”‘ + uid + ‘”)’, 1000);
change 1000(ms) to 3000-8000 (ms).
try this.
September 14th, 2009 - 23:04
hey steve,do know any host that i can install and use apc extension?
September 17th, 2009 - 12:46
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.
September 16th, 2009 - 13:52
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.
September 17th, 2009 - 12:50
Sorry, I don’t know anything about mod_security.
September 17th, 2009 - 05:59
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?
September 17th, 2009 - 12:57
That looks like it should work just fine. I guess I’ll need more information about the setup to know what’s going wrong.
October 6th, 2009 - 16:13
let progress bar work -
<input type="hidden"
must be BEFORE
<input type="file"
February 12th, 2010 - 05:46
Hi Steve,
This tutorial is really something. However, I’m running into a unique problem where I need to be able to run this script within a certain scope. For example I have a url that already uses $_GET['key']. http://www.domain.com/index.php?key=12345
Do you think you can assist me with getting this script work within my scope? Basically what happens is that the $_GET['key'] is needed to display the proper page, $_GET['uid'] gets in the way of this.
Any help would be appreciated.
February 12th, 2010 - 13:06
If I understand correctly, you need to have multiple variables in the URL. You just have to separate them with the & symbol, like this: index.php?key=12345&uid=12345
February 12th, 2010 - 15:53
Hi Steve,
I’ve figured it out. I’m actually going to drop the UID and use the key i’m already generating!
Thanks!
February 17th, 2010 - 10:05
I need help..
File uploads to server but the progress bar does not show anything..
You only see Upload Complete in white…
Can someone help?
February 17th, 2010 - 14:01
It could be a number of things, so I’d need more info to help. Are you sure APC is installed correctly with
apc.rfc1867 = On, and the HTTP server was restarted? What is the output of the APC section of phpinfo()?March 4th, 2010 - 04:39
Very nice tutorial. Thank you. I’ve got it working with a nice moving progress bar and such.
But .. the receiving page “upload.php” never gets loaded. And I want to show results from the processing of the uploaded file there.
Are there any solutions for that?
March 9th, 2010 - 05:37
Thanks for a great tutorial
However, im having trouble with the progressbar. When i start en upload, the iframe shows the progress bar, and starts at 0%. But it’s stuck at 0%, while the upload is going in the background. The file is successfully uploaded, but the bar still indicates 0% after the upload has completed.
You mentioned that PHP 5.2+ is required. I have PHP 4.4 with APC installed. Would i still need to upgrade php? That requires alot of script-updates from our webpages :X
March 10th, 2010 - 11:09
Yes, unfortunately this feature requires PHP 5.2 or greater. See: http://www.php.net/manual/apc.configuration.php#ini.apc.rfc1867
March 11th, 2010 - 16:38
hi Steve , Great tutorial.
This may seem so basic .. i’m new to this
I get apache error log ” failed to open stream – Permission denied in /var/www/html/upload.php on line 5
(ive already changed /www/uploads to /www/html/uploads to suit my distro.
file permissions on /uploads is 777 for the test … any ideas?.. thanks
March 12th, 2010 - 11:49
It sounds like a system configuration problem. Check to make sure the upload_tmp_dir directive in php.ini is not set to something not read/writable by PHP (it defaults to the system temp directory if not set). Also make sure you don’t have something like SELinux preventing the file write.
March 14th, 2010 - 15:07
Thanks Steve , works great now.
Also I cannot get the upload_form to work on a refering server,by putting upload_form on the refering server, leaving progress.php and getprogress.php on the home server.(that I know all works fine on).
The upload works , the progress (box) is drawn, but no % or progress is returned.
I have ammended the calls to getprogress.php and upload.php to /home_server/getprogress.php and /home_server/upload.php in upload_form.php.
could you please advise if I am trying something that will never work?
Thanks again for your help.
thanks in advance
David
March 15th, 2010 - 10:47
This is a common problem to run into. Trying to run AJAX calls across different domains is not possible in modern browsers for security reasons.
A possible way to work around this is to have a PHP script on the local server that fetches data from the remote server using cURL or something and outputs the results. Then you simply call that script with your AJAX, and it will work great since the data is coming from the same domain as far as the browser is concerned.
Here’s an example of what that proxy script might look like:
March 15th, 2010 - 22:59
Thanks Steve,
i’ll try that, makes sense
I appreciate the heads up on ajax across servers,
It was being denied but the perm’s seemed ok.
I’m glad you suggest php, ‘cos it’s the only thing I know a bit of
Thanks again
March 16th, 2010 - 01:20
Steve,
That’s it… worked straight off the batt.
I called your script “fetch.php” on the local server,
replaced getprogress.php with fetch.php in the ajax part of upload_form.php,
whalla!
Thinking maybe to change setimeout to 10x for reduced traffic.
Thanks again
March 27th, 2010 - 20:05
Steve,
Cool tutorial, but I’ve been trying all day and can’t get it to work on my local server. The progress bar initializes, but shows no progress until the script is complete, then shows “Upload Complete!” Any idea what could be causing this?
I’m using exact copies of your scripts (except for the $path variable, of course) so I assume it has something to do with my local environment, i.e., Apache, PHP, or APC configuration. I made sure that ‘apc.rfc1867=on’ is showing in my APC settings – are there any other settings I could look at? Could you give me a link to a page that displays the settings on your demo server, so I can compare?
This script is the best and simplest I’ve run across, and looks like it would do exactly what I want, if I can just get it to work. Any help would be greatly appreciated.
March 29th, 2010 - 16:19
Still no success, and now I have a new problem. I uploaded the script to the web host I’m using, tested it, and came up with a totally different problem. On this server, apc_fetch seems to be returning NULL or 0. I have checked the settings over and over again, and they are identical to those of my local server, on which apc_fetch returns the correct value.
The problem on the local server seems to be that the function on line 38 -triggered by HttpRequestObject.onreadystatechange – just simply isn’t running until the process completes. I have looked at both of these until I’m cross-eyed, and I cannot find the problem. Any ideas?
April 7th, 2010 - 08:12
I have PHP 5.2.4 and APC is active and rfc1867 is on. I get an immediate “Upload Complete” on smaller files and on larfer files (test ones were 35 Mb) I get 0% complete and then nothing. This is not browser specific.
Overall this is perfect for what we are doing but we need large file size capability so I’m hoping you have some idea on this.
Also, thank you for doing this, so much out there but litte that is concise and straight-forward.
April 8th, 2010 - 06:41
Took a little while but I figured out that it was the default settings on PHP limiting file sizes and nothing to do with this code. I set my upload_max_filesize and post_max_size in the php.ini to 100M and it works fine now.
Thank again and hope this helps others who might be new to using PHP and want this great function on their site.
April 29th, 2010 - 22:46
This above script is working fine in FF, IE. but in Chrome it doesn’t show progress status. Can any explain me why its going wrong ?
July 6th, 2010 - 08:47
Hey Steve. Very clear tutorial, everything is explained nicely.
I have APC installed alright but I can’t get this to work. apc_fetch() is just not getting anything, the bar keeps showing 0%. At first I thought this was my server configuration, some kind of problem with Zend or something, but imagine my surprise when I tried the example link you give here and noticed it does the exact same thing. I tried every major browser’s latest version, none of them work. This cannot possibly be a client side issue, right? Can you check and see if you get the same issue?
Thank you
July 6th, 2010 - 09:29
Yeah I was actually looking at it yesterday and found that APC was not tracking uploads for some reason. I haven’t been able to figure out why, but I did have better luck with http://pecl.php.net/package/uploadprogress in place of APC.
To use that, you have to change the name of the hidden field from APC_UPLOAD_PROGRESS to UPLOAD_IDENTIFIER and your getprogress.php would look like this: