Subscribe by Email

Today we’re going to be creating a file uploader using HTML5 drag and drop, along with the file reader API and some PHP. We’ll also be using local storage to remember which files were uploaded by the user.

Getting Started

For this tutorial I’m using jQuery and an icon font called symbolset. If you don’t want to get symbolset you could use an alternative or just not use a symbol font all together! So first off, we need to include the appropriate files in our index.html file:

jQuery

Effectively what we want to do is get the Data URI for all the images that the user drags into the drag area. Data URIs represent the data of the image. Basically, what we want to do at the simplest level is put all the data URIs the user drags into the box into an array, and post it to a PHP file. This PHP file will process the URIs and upload them to the server.

To begin, we need to initiate some variables:

$(document).ready(function() {
// Makes sure the dataTransfer information is sent when we
// Drop the item in the drop box.
jQuery.event.props.push('dataTransfer');
var z = -40;
// The number of images to display
var maxFiles = 5;
var errMessage = 0;
// Get all of the data URIs and put them in an array
var dataArray = [];

Next we need to bind a function to the drop event. This will mean when the user drops something onto the drop area we can run a function to do what we want to do. We want to support multiple file uploads so we will run each in jQuery to run a function for each file dragged into the drag area.

$('#drop-files').bind('drop', function(e) {
// This variable represents the files that have been dragged
// into the drop area
var files = e.dataTransfer.files;
// Show the upload holder
$('#uploaded-holder').show();
// For each file
$.each(files, function(index, file) {

Now we want to check for any errors. If the file isn’t an image, we will show a little quirky error in the drop box.

When the user drops an image in the drop box, the first 5 will be shown as images. All the rest will be shown as a little +8 which when clicked will show a drop down of the files uploaded. On top of the first 5 images we’ll place the upload button. To make sure the upload button is positioned correctly, we check the position based on how many files are in the dropped files area.

Now we need to figure out what to do when the user presses the upload button. As I mentioned, we want to pass the data to a PHP file. We’ll also show a little CSS loading bar. We’re using each again to upload each file one by one. This is where our data URI array comes into play.

We want to post the data to a file called upload.php (create this file!). We use jQuery’s AJAX functions to accomplish this. In the callback function for the post, we’ll update the loading bar and check if the loading process is finished completely.

The PHP file will return some data which we must interpret. One piece of this is the name we generate for the file, and the other is whether or not the file upload was successful. This data is separated by a colon so we have to separate it into an array and use the appropriate data. We then combine all of this data and append it to the ‘uploaded files’ section.

And that’s all the Javascript! The next bit is uploading the data URI to the server, and for this we need to use PHP.

PHP

The PHP isn’t particularly hard. Our PHP file will be called upload.php. The data URI will be encoded using base 64. We have to decode it to begin with by taking apart the data URI, grabbing the data and changing it as appropriate. After that we find the mime type, create a random name, and move the file into a variable. From there we can upload the file to a server and show a success or failure message. For this particular tutorial we’re using a folder called images to store all our images in.

And now we’re done! Try out the demo (I’ve disabled uploading to the server so you wont be able to access your uploaded files on this website), or you can download the files and try it yourself (everything will work in the download). I hope you’ve enjoyed this tutorial!

Support

As you’d imagine, this doesn’t work in the latest stable release of internet explorer. However, it should work fine in any other modern browser.

Hi!
It really great. Good base for my script.
I have 2 comments:
1, for big files (above 600kb) is not OK without hack the POST pars.
you should split the encoded file content into 800.000 characters ca.
and send the parts in separated post vars like filepart_1, filepart_2
after sending you can rebuild the file again.

2, i had problems with Firefox.
After hacking the binded drop event with this: e.originalEvent.stopPropagation(); e.originalEvent.preventDefault();
started work normally.

You can add the information to a database using a simple PHP query. Just create a database with the name (which is $randomName in the PHP code), and insert it into a table which has two fields (name and id). Make the ID auto incremental.

Then just have a php file called products.php that will gather the information:

Amazing plug-in, congratulations.
Another question related to variables.
I’d like to upload the images into different folders depending on the kind of image.
Can I call to a variable from upload.php for example upload.php?id=x

1. $getMime is a bad variable name. It contains the file extension, not the mime-type, so it’s misleading. It’s also named as if it’s a method, which is stylistically weird. To each their own, I guess :)
2. You do no input filtering on $_POST['name'] – whatever appears after the last ‘.’ character will be written to the filesystem, which isn’t ideal.
3. It’d be handy to modify the upload function to use jQuery’s serialize on a form so you could show how to associate other data with the images being uploaded (in the real world, images would likely be associated with a document ID or CSRF token, etc). Maybe outside of the scope of the tutorial, but you went and used a symbol font, so this isn’t much further :)

When i used it i found that sometimes the bit ii was dragging over wasn’t the correct bit and the site just viewed the picture in the browser. So I put this bit of code in after the dragenter bind to let them know that they weren’t in the right place

Excellent tutorial, I really like how you explain everything thoroughly. While I realize this is explicitly for images, showing how to modify for different file types would be a great addition. Also, I notice in google chrome, it’s not submitting via $_POST but via $_FORM, found that interesting.

This is awesome!! Thank you so much for making it look so simple yet affective. I have used your PHP sample.. but on my localhost it doesnt seem to be saving the files to the images folder.
However, when I specify a Hardcoded full path like “c:\Sam” it works!

I tried giving the full path of the images folder (eg: c:\inetpub\wwwroot\myapp\images) , again this doesnt work :(
Is there a write access I need to set anywhere? I have checked Read/Write/Modify prvileges for this folder. Yet I get error when using the script.
Any help will be great appreciated!
Thanks again:)

where to use the insert into sql? because i am having problems finding out where to throw it in. after following this toturial :D
i want it too throw the images into my database after uploading and not just out in nowhere. thx for replying :)

I noticed when I dragged and dropped multiple photo files into drop box, sometimes the sequence of the files is not in order.
For example, these are the files that I want to upload in sequence : DSC08481.jpg, DSC08482.jpg, DSC08483.jpg , DSC08484.jpg.
I choose all these files, drag and drop them into drop box. I use console.log() to see data URI being push into array :
console.log(file.name);
dataArray.push({name : file.name, value : this.result});
I found out the files are not in order that I expected.
It was : DSC08483.jpg, DSC08481.jpg, DSC08482.jpg , DSC08484.jpg.

Hey John sorry for the slow reply. I think this is something I looked into when I was making this and unfortunately I couldn’t find a way to do it. It might be possible if you query every image upload, put them in an array and ordered them by name, but that seems like a lot of work! I will look at updating this in the near future.

Firstly wanted to say thanks, I used this for a uni project and it was perfect. There was just one thing I wanted to ask though, is there a way to stop the browser displaying the dropped image if they miss the drop zone? I tried the bit of script that another user posted last year but it does nothing.

Hey Johnny, it’s working fine until this line $.post(‘upload.php’, dataArray[index], function(data) {…}); when it hits this line it’s not working. You said.. We use jQuery’s AJAX functions to accomplish this.But it’s not working for me.I’m trying this code for asp.net Visual studio 2008.And where should i add inside the php . Reply me asap. Thanks for your help.

I really like the Drag and Drop File Uploader. I am having a little bit of trouble outputting the dragged file. I created an images folder to accompany the request in the PHP file, however after i hit upload and it says upload complete, I go to my image folder and there are no images in the folder. Is there a specific folder I need to put it in? Any insight or resources would be of great help. Thanks

Dear Johnny, It’s OK now. i can upload various file type such as *.ai, *.eps, *.pdf , etc. i need only one that it can’t accept large file. i think i can solve it. thanks you so much Johnny. you have done great work.

Very interesting code. What’r the chances that once the docs are uploaded, a button can be pressed and the docs (essentially attachments) are then placed into the user’s default email client (such as Outlook) and can then be sent off to a recipient?

// Use a regular expression to trim everything before final dot
var extension = filename.replace(/^.*\./, ”);

// If there is no dot anywhere in filename, we would have extension == filename,
// so we account for this possibility now
if (extension == filename) {
extension = ”;
} else {
// if there is an extension, we convert to lower case
// (N.B. this conversion will not effect the value of the extension
// on the file upload.)
extension = extension.toLowerCase();
}

I used switch statement for future expansion to include excel and doc files.

I get a warning that I am trying to upload an image but the MIME type is application/pdf. However the file is successfully uploaded.
I think that the problem lies within $encodedData of upload.php and am working on solving this.

what am I missing? I have tried the demo but nothing seems to happen–the upload just sits there. No progress bar activity. Do I need to create the images/ dir? I tried in the folder with the index.html, and on the root.