Multiple File Upload With Progress Bar Using jQuery
Sep 8th, 2009 - 38 Comments »
Posted in jQuery
The default browser file input boxes do not allow multiple file selection for uploading at once and also do not provide any visual clue as to how much of the files selected have uploaded. Earlier I wrote about multiple file upload using AJAX, but that did not provide multiple file selection and a progress bar.
Today I am going to show you how to create a multiple file upload form that allows multiple file selection using Ctrl/Shift keys and also displays a progress bar for each of the selected files while they are uploading.
For this tutorial, you will need the all powerful jQuery library(latest version) and SWFUpload jQuery Plugin.
Folder Structure
Place the jQuery library in js folder, extract the SWFUpload jQuery Plugin somewhere and copy the jquery.swfupload.js in the src folder to the js folder. Also, copy the swfupload folder inside vendor folder of SWFUpload jQuery Plugin to js Folder. Here’s what your folder structure should look like.

Add reference to jQuery library and then jquery.swfupload.js in the head tag of your page.
HTML Structure
Since we will be using SWFUpload, we’ll need a container that will act as placeholder for SWFUpload button, and a list to show the queue of files.
<div id="swfupload-control"> <p>Upload upto 5 image files(jpg, png, gif), each having maximum size of 1MB(Use Ctrl/Shift to select multiple files)</p> <input type="button" id="button" /> <p id="queuestatus" ></p> <ol id="log"></ol> </div>
CSS Styles
Here are some CSS styles to stylize our File Uploader, modify them as you want. Important ones are .progressbar and .progress that define the progress bar for file upload, you can adjust their height and color.
#swfupload-control p{ margin:10px 5px; font-size:0.9em; }
#log{ margin:0; padding:0; width:500px;}
#log li{ list-style-position:inside; margin:2px; border:1px solid #ccc; padding:10px; font-size:12px;
font-family:Arial, Helvetica, sans-serif; color:#333; background:#fff; position:relative;}
#log li .progressbar{ border:1px solid #333; height:5px; background:#fff; }
#log li .progress{ background:#999; width:0%; height:5px; }
#log li p{ margin:0; line-height:18px; }
#log li.success{ border:1px solid #339933; background:#ccf9b9; }
#log li span.cancel{ position:absolute; top:5px; right:5px; width:20px; height:20px;
background:url('js/swfupload/cancel.png') no-repeat; cursor:pointer; }
The JavaScript Code
The JavaScript code is a bit bulkier but it is not that difficult to understand as it looks.
$(function(){
$('#swfupload-control').swfupload({
upload_url: "upload-file.php",
file_post_name: 'uploadfile',
file_size_limit : "1024",
file_types : "*.jpg;*.png;*.gif",
file_types_description : "Image files",
file_upload_limit : 5,
flash_url : "js/swfupload/swfupload.swf",
button_image_url : 'js/swfupload/wdp_buttons_upload_114x29.png',
button_width : 114,
button_height : 29,
button_placeholder : $('#button')[0],
debug: false
})
.bind('fileQueued', function(event, file){
var listitem='<li id="'+file.id+'" >'+
'File: <em>'+file.name+'</em> ('+Math.round(file.size/1024)+' KB) <span class="progressvalue" ></span>'+
'<div class="progressbar" ><div class="progress" ></div></div>'+
'<p class="status" >Pending</p>'+
'<span class="cancel" > </span>'+
'</li>';
$('#log').append(listitem);
$('li#'+file.id+' .cancel').bind('click', function(){ //Remove from queue on cancel click
var swfu = $.swfupload.getInstance('#swfupload-control');
swfu.cancelUpload(file.id);
$('li#'+file.id).slideUp('fast');
});
// start the upload since it's queued
$(this).swfupload('startUpload');
})
.bind('fileQueueError', function(event, file, errorCode, message){
alert('Size of the file '+file.name+' is greater than limit');
})
.bind('fileDialogComplete', function(event, numFilesSelected, numFilesQueued){
$('#queuestatus').text('Files Selected: '+numFilesSelected+' / Queued Files: '+numFilesQueued);
})
.bind('uploadStart', function(event, file){
$('#log li#'+file.id).find('p.status').text('Uploading...');
$('#log li#'+file.id).find('span.progressvalue').text('0%');
$('#log li#'+file.id).find('span.cancel').hide();
})
.bind('uploadProgress', function(event, file, bytesLoaded){
//Show Progress
var percentage=Math.round((bytesLoaded/file.size)*100);
$('#log li#'+file.id).find('div.progress').css('width', percentage+'%');
$('#log li#'+file.id).find('span.progressvalue').text(percentage+'%');
})
.bind('uploadSuccess', function(event, file, serverData){
var item=$('#log li#'+file.id);
item.find('div.progress').css('width', '100%');
item.find('span.progressvalue').text('100%');
var pathtofile='<a href="uploads/'+file.name+'" target="_blank" >view »</a>';
item.addClass('success').find('p.status').html('Done!!! | '+pathtofile);
})
.bind('uploadComplete', function(event, file){
// upload has completed, try the next one in the queue
$(this).swfupload('startUpload');
})
});
Code Explanation
Since we are using SWFUpload jQuery Plugin, firstly we initialize it on the placeholder element using the $('#placeholder').swfupload({ settings }) function and pass it a settings object that defines various parameters like server side file that will handle uploads, maximum size of the file, number of maximum uploads, allowed file types, button url, button size etc. For complete detail of settings you can use, refer to SWFUpload docs.
At this stage, your file upload script will work but will not show any visual clue to users about the upload. SWFUpload fires certain events that we can use to provide information to user about the file uploads. So, next thing is to bind functions to various events to show required output. That’s what all bind calls are doing. They are pretty much self-explanatory.
Limitations
Since this script uses SWFUpload to upload files, which requires flash plugin, so this will not work if flash plugin is not installed in end user’s browser. Make sure to provide an alternative upload form so that users without flash can upload files.
Also, SWFUpload has some known issues when used on linux systems and if user is behind proxies. Make sure to read them before you use it in production environment.
Bookmark n Share
Subscribe to Full RSS Feed
If you found this article
useful, then consider subscribing to our
RSS Feed or
e-mail updates to stay updated with
latest Web Design/ Development articles. You can also follow @webdevplus on twitter for latest updates.
38 Responses (Add Your Comment)
Comments are closed for this post.



Very Nice and helpful Tutorial. Will try this in one of my next projects with uploads.
Daniel
thanks! Daniel
Really great script, always had problems with multiple uploads, I built my own but using 5 input fields, this is much more elegant. I create session variables with my images created (timestamped so as not overwrite other images) and think this would be awesome to adapt my way of uploading images with this brilliant script.
Thanks
David Bolton
Hi,i found several flash dependent fle uploaders. What is the main reason preventing to achieve the same functionality using pure Javascript code?.Thanks
Safari 4 has this functionality built in http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html and I wrote about Firefox 3.6a1 support for multiple drag and drop file uploading http://www.thecssninja.com/javascript/drag-and-drop-upload
This is great. I’m trying to modify it so I can upload files directly to Amazon S3.
Two things
1) When I center the button/progress area, the progress bar starts in the middle and spans both sides until complete. This is awkward, can I would like it to proceed left to right. How do I do this?
2) How can I add a “stop upload” for uploads that are in progress?
Excellent tutorial to implement multiple image upload with progressbar. Thanks for sharing.
This is a great script, however I found that there’s some problems in it. The upload procedure does not upload the files greater then x mb althoug I did the necesary modifications. It generates the ok messages, doesn’t give any warnings or errors, but still the uploaded file isn’t found in the upload folder.
Anyway, thanks for sharing.
sorin, in case of swfupload, it gives success message only on successful upload to the server and not on whether your server side script was able to move it to specified folder or not.
You’ll have to set up uploadSuccess function binding in a way that it tests serverData variable and shows message accordingly.
Also, try enabling the debug mode of swfupload by setting
debug:truein javascript code and see what the server side response is.Thanks for this tutorial! I’m using this in my website but it won’t work.
I tested it with the source files and it doesn’t work. When I do an upload it says that it is uploading but it keeps saying uploading… and my upload bar goes directly to 100%. When I see in the map uploads there is nothing in it. Can somebody please help me with this problem?
great work! thanks for sharing
hi,
i need a form to upload the files with text field , is it possible
Hey very nice script…. I have a question!!!
is it possible to post some data with the files????
Thanks in advance…
vinay, here’s an example of how to post some data while using swfupload, http://demo.swfupload.org/v220/formsdemo/index.php
I hope this helps you find the solution
I am using this plugin, and I think its really nice..
I just want to know if there is any way to get the resolution of the image just when the image is slected and added to queue… Actually i want to show a thumbnail of the image being uploaded but i cant do it with plain JS..
This type of operation though not possible with regular JS, but here’s a nice trick that should do the job for you.
http://community.invisionpower.com/topic/226158-thumbnail-preview-before-image-upload/
Also, refer to the swfupload docs to find out the path to selected image
Thanks for replying but i have already tried a similar thing before.. The problem is that in this way i cannot maintain the aspect ratio of the thumbnails and it looks really odd for portrait pics..
Maybe I can still do something if i can get the path of the image, but i couldn’t find any reference in the the SWFUpload docs..
“File Object{
…
name : string, // The file name. The path is not included.
…
}”
I’m displaying an animated wait image for the time being.. but its not wt i really want to do..
Does anyone there have any idea how to get the path of the image..?
Great tutorial! Can you advise on a method for detecting when *all* uploads are complete?
Found a solution for detecting ‘all uploads complete’ (I’m totally new to JS so apologies in advance!)
1) Within the (fileDialogueComplete) event set a global variable ‘totalFiles’ with the value of ‘numFilesQueued’
2) Within the (uploadSuccess) event split ‘file.id’ with ‘_’ and compare the last element in the array plus 1 with ‘totalFiles’.
If they are equal, all uploads are complete.
I would have liked to handle this all in the fileDialogueComplete event, but this event doesn’t get ‘file’ passed to it.. (Interested to learn how this could receive ‘file’).
Interested in feedback if there is a better way to achieve this.
Thanks!
Sean
This script is just what I need. I have successfully managed to increase the # of uploads from 5 to suit my needs. This is working fine.
I’m having issues with increasing the file size allowed. I have changed the java/php script together. I does allow the file to be uploaded on my site, but the file never moves into the ‘uploads’ folder. Can someone please point me in the correct direction.
Thanks….Mike
Please disregard my last post. It was my mistake, some of my changes did not take.
I have now sucessfully allowed up to 60 uploads, with max file size of 5MB.
Now, because of this script, my website is done!!
Great script!
Is there any way to pass information to the PHP script processing the uploads? Specifically, I need to pass POST or GET variables so that the php script can update a database with the user’s name/id and also an ID for the page they’re uploading from.
I’m able to get files into my filesystem and even rename them, but this lack of other information is causing issues. I’m a bit of a newbie to javascript, so I’m using the demo more or less as written.
Actually, I think I’ve figured it out. I’m using php, so I take information from the page that calls the script and insert a GET query line in the ‘upload_url’ variable so it reads something like:
upload_url: “upload_swf.php?username=joe&user_id=1&subject_id=285″,
Hey exellent upload script! I’ve just about had enough of trying to force others to work but this works straight outta the box. Awesome!
One thing I’d like to integrate though is email support. I want to get an email when users add a file to the server as well as add their name and email which would come with the email.
Any ideas how I’d do this (Im ok with php but not excellent)
Cheers!
I would like to change the file name to represent MMYYDD, once it has been uploaded and moved the the ‘upload’ folder. That way if someone uploads the same file name, it wont overwrite the first file. Can someone please help me accomplish this or point me in the correct direction.
I know its an addition to the php script, just dont know what to add and also where to add it.
I appreciate help on this, thanks
Mike D.
@Mike
in your upload script use the date function to format your timestamp
add the timestamp to the beginning of the file name
save that filename
echo a success string back with your new filename
in your jquery script parse the response to check for error string
if not error, use the serverdata as the new filename
???
I am using this plugin in my own framework and had to pass the PHPSID through the query string to gain access to the session. I suppose this is a cookie issue with flash ? Or is the cookie plugin for swf required ?
Very nice!
However, javascript and flash are too HUGE dependencies…
“provide an alternative upload”
…hell, might as well not use it if you have to double the amount of work it takes. Unusable candy.
Great script. Everything seems to be working well, except: The browser doesn’t see the uploaded files. The files are there on the server in the uploads directory (and I’m able to download them using ftp), but when I click on “view” on the progress bar, or type in the url of the file directly into the browser, I get a 404 error. How weird is that?
Any ideas?
Thanks,
Kyle
Ooops, I meant to say, 403 error in my last post.
Kyle
Works well. I tried to upload 500 files at one go but go this strange error.
“Sorry. Select fewer Files.”
How can I remove this limit. My requirement is to upload 5000 images one shot and the client needs this badly.
Please help.
Thanks
Jad
What about people uploading executable files? If I simply name a php file or any file with a .jpg at the end then I can execute it. I have this problem with all the upload scripts on the net.
Security is always on the top of my priority list so I’m wondering how can I stop this from happening. I pretty much just hacked my own site in like 2 seconds with this script and I know nothing about that sort of thing so someone who does could do some serious damage.
Any thoughts on the subject?
Is there any way to send any varible to ‘upload-file.php’?
Why doesn’t ‘upload-file.php’ get $_GET variables?
Why ;p can’t i contact mysql?