HTML5 File Uploads with jQuery

Demo Download

Today we will be developing a small web application called Upload Center, that will allow people to upload photos from their computers by dragging and dropping them onto the browser window, possible with the new HTML5 APIs exposed by modern browsers.

The photos will have a preview and a progress bar, all of which controlled on the client side. Currently, the photos are only stored in a folder on the server, but you could improve it any way you like.

What are HTML5 File Uploads?

Uploading files using HTML5 is actually a combination of three technologies - the new File Reader API, the also new Drag & Drop API, and the good ol' AJAX (with the addition of binary data transfer). Here is a description of a HTML5 file upload process:

  1. The user drops one or more files from their file system to the browser window by dragging. Browsers that support the Drag & Drop API will fire an event, which alongside other useful information, contains a list of files that were dropped;
  2. Using the File Reader API, we read the files in the list as binary data, and store them in memory;
  3. We use the new sendAsBinary method of the XMLHttpRequest object, and send the file data to the server.

Sounds complicated? Yes, it could use some optimization. Fortunately, there are jQuery plugins that can do this for us. One of them is Filedrop, which is a wrapper around this functionality, and provides features for limiting maximum file size and specifying callback functions, which is really handy for integrating it into your web applications.

Currently file uploads work only in Firefox and Chrome, but upcoming major versions of the other browsers also include support for it. A simple fallback solution for older browsers would be to display a regular file input dialog, but we won't be doing this today, as we will be focusing our attention on using HTML5.

So lets get started!

The HTML

The markup of our Upload Center couldn't be simpler. We have a regular HTML5 document, which includes our stylesheet and script.js file, the Filedrop plugin and the jQuery library.

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>HTML5 File Drag and Drop Upload with jQuery and PHP | Tutorialzine Demo</title>

        <!-- Our CSS stylesheet file -->
        <link rel="stylesheet" href="assets/css/styles.css" />

        <!--[if lt IE 9]>
          <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    </head>

    <body>

        <header>
            <h1>HTML5 File Upload with jQuery and PHP</h1>
        </header>

        <div id="dropbox">
            <span class="message">Drop images here to upload. <br /><i>(they will only be visible to you)</i></span>
        </div>

        <!-- Including The jQuery Library -->
        <script src="http://code.jquery.com/jquery-1.6.3.min.js"></script>

        <!-- Including the HTML5 Uploader plugin -->
        <script src="assets/js/jquery.filedrop.js"></script>

        <!-- The main script file -->
        <script src="assets/js/script.js"></script>

    </body>
</html>

The only div that the Filedrop interacts with, is #dropbox. We will pass this element to the plugin, which will detect when a file is dropped on top of it. The message span is updated if there is an error condition (for example if your browser does not support one of the HTML5 APIs that this example relies on).

html5-jquery-php-upload-progress.jpg

Later, when we drop a file, our jQuery code will display a preview by adding the following markup to the page:

<div class="preview done">

    <span class="imageHolder">
        <img src="" />
        <span class="uploaded"></span>
    </span>

    <div class="progressHolder">
        <div class="progress"></div>
    </div>

</div>

This snippet contains a preview of the image (the source attribute is going to be populated with a DataURL of the picture) and a progress bar. The whole preview can have the ".done" class, which causes the ".uploaded" span to show up (it is hidden by default). This span has the green check mark as its background, and indicates the upload is complete.

Great, lets move on to our script.js file!

The jQuery Code

As all of the actual file transfer functionality is handled by the Filedrop plugin, we only need to call it and pass a few callbacks, so we can hook it to our Upload Center. We will be writing a small PHP script that handles the uploads on the server in the next section.

The first step is to write a helper function that takes a file object (a special object which is created by the web browser on file drop, and has properties like file name, path and size), and creates the markup for previewing the upload.

assets/js/script.js

var template = '<div class="preview">'+
                        '<span class="imageHolder">'+
                            '<img />'+
                            '<span class="uploaded"></span>'+
                        '</span>'+
                        '<div class="progressHolder">'+
                            '<div class="progress"></div>'+
                        '</div>'+
                    '</div>'; 

    function createImage(file){

        var preview = $(template),
            image = $('img', preview);

        var reader = new FileReader();

        image.width = 100;
        image.height = 100;

        reader.onload = function(e){

            // e.target.result holds the DataURL which
            // can be used as a source of the image:

            image.attr('src',e.target.result);
        };

        // Reading the file as a DataURL. When finished,
        // this will trigger the onload function above:
        reader.readAsDataURL(file);

        message.hide();
        preview.appendTo(dropbox);

        // Associating a preview container
        // with the file, using jQuery's $.data():

        $.data(file,preview);
    }

The template variable holds the HTML5 markup of the preview. We get the DataURL of the image (a base64 encoded representation of the image bytes) and add it as the source of the image. Everything is then appended to the dropbox container. Now we are left with calling the filedrop plugin:

assets/js/script.js

$(function(){

    var dropbox = $('#dropbox'),
        message = $('.message', dropbox);

    dropbox.filedrop({
        // The name of the $_FILES entry:
        paramname:'pic',

        maxfiles: 5,
        maxfilesize: 2, // in mb
        url: 'post_file.php',

        uploadFinished:function(i,file,response){
            $.data(file).addClass('done');
            // response is the JSON object that post_file.php returns
        },

        error: function(err, file) {
            switch(err) {
                case 'BrowserNotSupported':
                    showMessage('Your browser does not support HTML5 file uploads!');
                    break;
                case 'TooManyFiles':
                    alert('Too many files! Please select 5 at most!');
                    break;
                case 'FileTooLarge':
                    alert(file.name+' is too large! Please upload files up to 2mb.');
                    break;
                default:
                    break;
            }
        },

        // Called before each upload is started
        beforeEach: function(file){
            if(!file.type.match(/^image\//)){
                alert('Only images are allowed!');

                // Returning false will cause the
                // file to be rejected
                return false;
            }
        },

        uploadStarted:function(i, file, len){
            createImage(file);
        },

        progressUpdated: function(i, file, progress) {
            $.data(file).find('.progress').width(progress);
        }

    });

    var template = '...'; 

    function createImage(file){
        // ... see above ...
    }

    function showMessage(msg){
        message.html(msg);
    }

});

With this, every valid image file that is dropped on the #dropbox div gets uploaded to post_file.php, which you can see in the next section.

html5-jquery-php-upload-done.jpg

The PHP Code

On the PHP side of things, there is no difference between a regular form file upload and a drag and drop one. This means that you can easily provide a fallback solution to your application and reuse the same backend.

post_file.php

// If you want to ignore the uploaded files,
// set $demo_mode to true;

$demo_mode = false;
$upload_dir = 'uploads/';
$allowed_ext = array('jpg','jpeg','png','gif');

if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){
    exit_status('Error! Wrong HTTP method!');
}

if(array_key_exists('pic',$_FILES) && $_FILES['pic']['error'] == 0 ){

    $pic = $_FILES['pic'];

    if(!in_array(get_extension($pic['name']),$allowed_ext)){
        exit_status('Only '.implode(',',$allowed_ext).' files are allowed!');
    }   

    if($demo_mode){

        // File uploads are ignored. We only log them.

        $line = implode('       ', array( date('r'), $_SERVER['REMOTE_ADDR'], $pic['size'], $pic['name']));
        file_put_contents('log.txt', $line.PHP_EOL, FILE_APPEND);

        exit_status('Uploads are ignored in demo mode.');
    }

    // Move the uploaded file from the temporary
    // directory to the uploads folder:

    if(move_uploaded_file($pic['tmp_name'], $upload_dir.$pic['name'])){
        exit_status('File was uploaded successfuly!');
    }

}

exit_status('Something went wrong with your upload!');

// Helper functions

function exit_status($str){
    echo json_encode(array('status'=>$str));
    exit;
}

function get_extension($file_name){
    $ext = explode('.', $file_name);
    $ext = array_pop($ext);
    return strtolower($ext);
}

The script runs some checks on the HTTP method that was used to request the page and the validity of the file extension. Demo mode is mainly for demo.tutorialzine.com, where I don't want to store any file uploads (if you don't call move_uploaded_file in your script, the file is deleted automatically at the end of the request).

Now lets make it pretty!

The CSS Styles

I left out the parts of the stylesheet that are not directly related to the uploads. You can see everything in styles.css.

assets/css/styles.css

/*-------------------------
    Dropbox Element
--------------------------*/

#dropbox{
    background:url('../img/background_tile_3.jpg');

    border-radius:3px;
    position: relative;
    margin:80px auto 90px;
    min-height: 290px;
    overflow: hidden;
    padding-bottom: 40px;
    width: 990px;

    box-shadow:0 0 4px rgba(0,0,0,0.3) inset,0 -3px 2px rgba(0,0,0,0.1);
}

#dropbox .message{
    font-size: 11px;
    text-align: center;
    padding-top:160px;
    display: block;
}

#dropbox .message i{
    color:#ccc;
    font-size:10px;
}

#dropbox:before{
    border-radius:3px 3px 0 0;
}

/*-------------------------
    Image Previews
--------------------------*/

#dropbox .preview{
    width:245px;
    height: 215px;
    float:left;
    margin: 55px 0 0 60px;
    position: relative;
    text-align: center;
}

#dropbox .preview img{
    max-width: 240px;
    max-height:180px;
    border:3px solid #fff;
    display: block;

    box-shadow:0 0 2px #000;
}

#dropbox .imageHolder{
    display: inline-block;
    position:relative;
}

#dropbox .uploaded{
    position: absolute;
    top:0;
    left:0;
    height:100%;
    width:100%;
    background: url('../img/done.png') no-repeat center center rgba(255,255,255,0.5);
    display: none;
}

#dropbox .preview.done .uploaded{
    display: block;
}

/*-------------------------
    Progress Bars
--------------------------*/

#dropbox .progressHolder{
    position: absolute;
    background-color:#252f38;
    height:12px;
    width:100%;
    left:0;
    bottom: 0;

    box-shadow:0 0 2px #000;
}

#dropbox .progress{
    background-color:#2586d0;
    position: absolute;
    height:100%;
    left:0;
    width:0;

    box-shadow: 0 0 1px rgba(255, 255, 255, 0.4) inset;

    -moz-transition:0.25s;
    -webkit-transition:0.25s;
    -o-transition:0.25s;
    transition:0.25s;
}

#dropbox .preview.done .progress{
    width:100% !important;
}

The .progress div is positioned absolutely. Changing its width (in percent) makes for a natural progress indicator. Throw in a 0.25 transition, and you have animated increments which would be a bit tricky to do with jQuery alone.

With this our HTML5 Upload Center is complete!

We're done!

You can use this as a starting point for a file upload service, HTML5 gallery, file manager or your app's new admin panel. Add your thoughts or suggestions in the comments.

Bootstrap Studio

The revolutionary web design tool for creating responsive websites and apps.

Learn more

Related Articles

...very nice app, tnx ! Only thing is that i personally still prefer an "old school" select button instead of drag and drop for file selection before upload... but i guess it won't be too difficult modifying the code a little bit to achieve this...

Martin Angelov

The same PHP script can be used to handle both regular and drag and drop uploads, so you only have to show a form with a file input box to make it work.

yes thanks !

Andrew Biggart

I have tried displaying the following form instead of the "Your browsers does not support drag and drop uploadfs!" message which I have got working.

<form method="post"><input type="file" name="pic" id="pic" /><input type="submit" value="Upload" /></form>

But how do I control the action of the form so that it uploads the image? I have tried changing the form action to post_file.php but I keep getting the "Something went wrong with your upload!" error.

I'm just not sure how I go about doing it?

You're actually pretty close, but you forgot enctype attribute in the form tag.
This will work:
<form method="post" action="test.php" enctype="multipart/form-data"><input type="file" name="pic" id="pic" /><input type="submit" value="Upload" /></form>

However, this will only upload the image to the webserver. You'll need to write something yourself to actually display the image on the page.

Added a form, but it's not working...I'd like both the dra/drop, but also a file select box too, in case the user doesn't want to resize his window...how to I attach the form to replicate the drag/drop script?

An interesting article well worth reading!

Codeforest

Very nice tutorial.

But, demo is not working for me in FireFox 6.0.2.

Martin Angelov

Quite a few people are testing the demo at the moment, so it is probably something temporary with my webhost. It is tested and working in Firefox 6.0.2.

I am planning to move the site to a dedicated vps over the weekend, so I hope everything will work as it should from then on.

Congratulations, really a nice tutorial. How do I add the category name in the database column when loading? is it possible?

Guillaume

Really nice scripts and also beautiful design, Thanks.

I have this form working but it only seems to work for your PHP script. My company uses an external upload handler which requires the name of the input file field be 'data', a separate field for image caption (the name of this field must be 'caption'), and the form's enctype must be 'multipart/form-data. Can I still use this uploader to achieve what I am attempting?

Martin Angelov

You will have to change the upload process. Maybe add a caption after the upload is complete?

Well, what to say?

You are simply awesome, you are also an amazing designer.

Good job Martin!

I was thinking to do this but you beat me to it. Great work. (:

It does not work in Opera.

Martin Angelov

Only Firefox and Chrome for now. As the script depends on the file upload APIs and not on specific browsers, once Opera adds support it would work automatically.

Because, it only work only in Firefox and Chrome, but upcoming major versions of the other browsers also include support for it. A simple fallback solution for older browsers would be to display a regular file input dialog, but we won’t be doing this today, as we will be focusing our attention on using HTML5. i mean, yo don't read text
carefully.

hello, gr8 tutorial like it.
wondering, how can i change it to accept remaining file extensions like zip, pdf, doc, txt?

i tried to add them in the script.js but error keep poppin up with image upload only...
thank you

Martin Angelov

You will need to add them in the PHP file as well (in the array with accepted extensions). However the script will attempt to generate previews for them, so you will probably want to display some generic image instead.

thank you

i tried to add this or replace in the post_file.php
$allowed_ext = array('jpg','jpeg','png','gif','doc','docx','pdf','xls','xlsx','pptx','ppt','rtf','txt','c','css')

but still, i get the image only error, when i tried to delete the javascript check image part, its not uploading either.. could you please further help me? thank you very much in advance.

Joshua Steenmeyer

In script.js file comment out lines 35 - 44

I think in the js it doesn't make that much sense, you'd rather do in the PHP something like

  if ($_FILES['userfile']['type'] == "video/mov"                     ||
      $_FILES['userfile']['type'] == "video/mpeg"                    ||
      $_FILES['userfile']['type'] == "video/quicktime"               ||
      $_FILES['userfile']['type'] == "video/qt"                      ||
      $_FILES['userfile']['type'] == "video/x-msvideo"               || 
      // this one is for MSIE on Mac & missing file-extension:
      $_FILES['userfile']['type'] == "application/x-macbinary"       ){
    $filetype = "ok";
    }

You are just.... awesome!

Thank you for this tutorial, very nice one as usual. And as Alberto said, even for graphic design you are good.

Shahrukh A. Khan

Great work team, I really appreciate the efforts, well I was just thinking to ask you am I allowed to use this for my personal use but I read your License thank you very much

izzy chuks

nice tuts, wud love to give it a try, my question is how do you delete/remove an uploaded file?

Martin Angelov

I am afraid you will have to do it yourself. The script only demonstrates how HTML5 uploads work, it doesn't handle other operations.

Massimiliano Arione

You can improve your PHP code.
First, get_extension() function is useless: just use pathinfo($file_name, PATHINFO_EXTENSION)
Next, exit_status() is not HTTP-friendly: you should send a proper header (e.g. 405 for method not allowed) along with error message

Martin Angelov

Great suggestions! Had forgotten about pathinfo.

A reader

This upload process is insecure. Putting all your trust on the file extension is a bad thing to do.

Sharun Kumar

Hey the PSD file is not available :/

I'm not sure if i'm having some sort of directory problem, but when i try and upload a file it progresses to about half way then stops. Anyone know why this could be?

Martin Angelov

The best way to find out is to install Firebug and inspect the request. It will give you an error code or some other indication on what might be causing the problem.

Skye Moroney

This happened to me - turned out to be the file permissions on the upload folder weren't writeable.

This happened to me too. If you have Chrome, go on your page, hit F12 to display the debugger.
Click on the "Network" tab.
Start an upload.
You should see some activity appearing.
Click on the element 'post_file.php' and then the "Preview" tab.
You should see what happened.
For me, the "uploads" directory was missing.

I had the same problem. Files got copied into the uploads folder but the progress bar stopped at 40-50%. Examining the html by the show source command in the web browser showed that the binary data was made from the pic i uploaded. So here was no feedback from the server to the browser displaying that the upload was done. Examining with phpinfo() showed that the webserver by the provider was running php 4XX. So no json was available.
My localhost runs php 5xx and everything works fine. I used the same files/code on both machines. Json must be available to run this script.

This is great stuff. Im wondering if it's possible to add a normal "select file" field to this and combine the two? Also, I'm wondering if it's possible to add the files to a queue instead of start the upload straight away, and then add an "upload" button?

Cheers

This is the error i am getting

Uncaught SyntaxError: Unexpected token / jquery-1.6.3.min.js:2
e.extend.parseJSON jquery-1.6.3.min.js:2
xhr.onload filedrop.js:223

Is the start time of the download screwing up the upload process?

Ah, i have managed to sort it

Cheers

ThomThom

What was is?

Hi Chriss,

I've got the same error, and I've been trying to fix it for the past couple of days.

How did you resolve this issue?

In case anybody runs into this same problem, its a permissions issue.

have the same problem.. what would be the solution?

If you're on Linux, try this command in the root folder of the project:

sudo chown www-data:www-data uploads

This will set the webserver as the owner of the uploads folder. The webserver username is www-data and the groupname is also www-data.

Also, if you're using Firebug, you should see the php-call in the net-tab. See what error it gives. If it's something with permissions, the above command will be the solution.

Bergaba Bidjeh

hi Chris,
I saw that you had and resolved this issue :

This is the error i am getting
Uncaught SyntaxError: Unexpected token / jquery-1.6.3.min.js:2
e.extend.parseJSON jquery-1.6.3.min.js:2
xhr.onload filedrop.js:223

I have now the same issue and I will be glad if you can explain to me how to resolve it.

regards,

Bergaba Bidjeh

marineking

always learning, nice job,orz

Could this be altered as to send files directly to a specified FTP folder on another FTP server than the website is hosted on?

I haven't got the programming skills, but I'm very interested in the potential of this file uploader.

Martin Angelov

I am afraid this is not possible. You will first need to transfer it to your server and then send it using PHP. Take a look at the FTP extension - it should be available in your installation.

I have a strange problem, the upload works fine, the files appear on the server but the progress bar doesn't show up at all or gets stuck at about 20%
CSS is linked correctly.
Anyone may know what could cause that?

Martin Angelov

The best way to pinpoint the problem is to inspect the upload with firebug - it will show you if and what errors are thrown on the server side.

Found the error: my web server had json disabled!
Enabled and works fine now.

You Sir are a saviour. I love this and it has solved a previous headache I was having with FancyUpload where I struggled to get the POST variables sending through with the Flash POST.

In this case I modified your dropbox.filedrop({ statement to add the data: { param1: function(){ blah blah } to get the value of a form select dropdown so that I could pass that with each filedrop. (as per weixiyen usage example)

Thanks

Absolutely awesome work dude! Got it to work a treat on local server using multiple file types. Now have to find out how :
(1) Use generic previews for .pdf and .doc files
(2) Set file size limits
Keep up the great work

Good tutorial! Thanks!

Good Totorial for me...thaks.

Hi Martin,

Excellent post and demo. Thank you for sharing! I have implemented this in my application but would like your, or the community's, suggestion on how to handle the deletion of one or more files as user are prone to uploading wrong stuff. Options I have considered include:

  1. Have upload REST API return a file identifier (uploadFinished) and bind that identifier to a href "delete" image. When clicked, delete file on the server.
  2. Keep filename unchanged on both client and server. Allow deletion of file (uploadFinished) using filename only, similar to #1.

If nether of these options are plausible, what have you and other done? The delete feature will make this tutorial more meaningful for real, everyday usage.

Thanks,

Chris

Martin Angelov

It would be best to have a real database behind it. Users should have some kind of identifier (you could use IP addresses, but it wouldn't be as reliable as a real registration). After a file is uploaded, you should store it on your server with unique name and insert a record in your files table. You should then return this name (or the Id of the file record) with the response and display a delete link as in your original idea. Clicking on the link would send an AJAX POST request to a backend script, which would validate if the file exists and the user is allowed to delete it.

This way users will only be able to delete files they uploaded themselves.

Exactly. Do you think you will extend this demo with the delete feature - I did send you some sample code. Or should I just extend this feature and discuss it on my own blog? Just giving courtesy by asking you, the original author. :)

Could this be modified to allow dropping a entire folder containing the images?

Thank you

Martin Angelov

The last time I checked, uploading entire folders with files is only supported in Google Chrome, so there won't be proper cross-browser support for some time to come.

Hy! nice tut. is there a way to download a final result of a drag and drop picture over picture? I am thinking of making a composition of several photos, one close to each other, or even one picture on top of other picture and in final the user can download his photo composition. Could you tell me if it can be done in the same way like drag and drop picture upload?

itoctopus

Hi Martin,

Kudos for the great work you did on this. This is unbelievable! I have tried it with multiple images and it worked like a charm!

Hi!

Really G-R-E-A-T job!!!!!!!!! It saved me a lot!!!! Thank you very much!!!!
xoxoxoxox

That is so nice and use full.
thanks tutorialzine.com

HTML 5 is on of the best things that have happened to web design in a while. Of course you could say that CSS made a bigger difference but for me HTML5 is better because we don't need flash or any other add-ons to play videos or any cool looking effects.
If we speak about HTML5 upload script I installed it on my translation service website, so people can now attach files with it and it replaced my flash based uploader.
Thanks! Much appreciate your effort!

benno_007

Epic work on this uploader mate.

For those who want to degrade to a normal file upload, just set up your form by default to use a file upload input box with a class 'jquery-filedrop'. Then, wrap the plugin code with this condition: if(!!FileReader && Modernizr.draganddrop)
It basically says: if you're capable of using this code, go ahead and use it. Otherwise, it'll stick you with your normal uploader.

E.G.:

// If they can use filereader and have drag and drop (would require modernizr for that part)
if(!!FileReader && Modernizr.draganddrop) {

    (function($){

    jQuery.event.props.push("dataTransfer");
        [..snip..]
    })(jQuery);

    $(function() {

      // ADD this code:
      // fuparent assumes the parent element will be replaced with the dropbox e.g. I use Zend Form, so the parent of the file input is a dd. Just wrap it in anything-div, span, whatever.

      var fileupload = $('.jquery-filedrop'), fuparent = fileupload.parent(), count = fileupload.length;
      fileupload.remove();
      fuparent.html('Drop images here to upload. <i>(they will only be visible to you)</i>');

     var dropbox = $('#dropbox'), ... [..snip..]

     // count can then be used to set the maxfiles and FileTooLarge error (saves you handling that in two places).
  }
}
Andrew Biggart

Why are parts of this code snipped off? I am trying to achieve a fallback but am finding it hard to follow the above instructions.

benno_007

The snipped bits were just the parts from the actual javascript plugin. The parts I put there are all that I changed.

benno_007

This is the full code that we're using at the moment:

http://jsfiddle.net/benno_007/ht8QK/

Note we also use Modernizr to detect dragndrop at the top

I cant seem to find out how to link this to dropbox? There is a part in the php file:

$upload_dir = 'uploads/';

But where do I get the upload directory from? I have tried to use an FTP server but no luck??

Hi,
Great tutorial!

Can I set the URL in dropbox.filedrop setting (script.js) to an external domain like this ?

dropbox.filedrop({ ..... maxfiles: 5, maxfilesize: 2, url: 'http://www.website.ext/post_file.php', .... },

thanks tutorialzine.com

Martin Angelov

You can't. This would be blocked by the browser's security policy.

Works like a charm! How ever - is there an easy way to pass along some kind of variable that in the end could be used to decide which upload directory the images will end up in?

I mean: making the index.html file as a php file like index.php?dir=4, select the variable and pass it through the js file and add it " url: 'post_file.php',", like " url: 'post_file.php?dir=4', and then use the variable in post_file.php.

I'm useless when it comes to js, but can do the php adjustments.

I had the same problem, because i'd like to create a map with pictures for every newsitem on my website. I figured out the solution!
I'll explain how i found it and how i use it.

If you open "jquery.filedrop.js" you see a list with default options of the filedrop function. One of them is "data: {}" wich you can use you pass on variables. I did not change "jquery.filedrop.js".

In "script.js" i put
"data: {item_id:document.form.id.value},"
right under
url: 'post_file.php',

This passes along the item_id of my news-item to post_file.php.
In "post_file.php" i can recall my item_id with $_POST['item_id']. Hope this was helpfull. And thanks to tutorialzine for posting this script!

I'm having difficulty with this part -- I also need to pass data in order to determine what subfolder to drop/upload into: however, I need to pass three variables. In firefox, if I declare data: ... in my script.js file, it renders the page, but does not perform upload, it simply opens the image in my browser, as if I have chosen "File > Open"

Any ideas?

Hi there. It is uploading the files okay, however it won't show the status bar and Firebug reports this:

$.data(file).find('.progress').width(progress); is not a function

and this

JSON.parse: unexpected character

....resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d...

Help would be appreciated, thanks :)

I had the same problem after i integrated the script into my website framework. I'm not very good with jquery but i figured that after integrating the script into my framework i had a problem with the URL path to the upload script (i was also using apache mod rewrite). So after fixing the URL, the script was working and i did not get this json error msg anymore.

Good luck, hope it helps.

Sebastian

Does anyone know how to fix the 4 MB max size limit?
I have changed the max post size and everything, so I'm pretty sure this is HTML5's fault.

Thanks!

Btw, you can test the bug on my website.

Sebastian

Whoops, I just realized I changed max_post_size instead of max_upload_size.
It works great now, I was wondering if there was a way to add a file browser so browsers that don't support drag and drop will also be able to upload?

Thanks!

Leandro Ribeiro

Thanks, very nice.
I'm porting for ASP.NET MVC. :D

Any update on porting this to ASP.Net?

Nestor Leone

Any luck on this ??? I'm trying to do so too, but i'm not that good on PHP.....

Can you modify this code for scaling the image and rename the file upload for example thum_image1.jpg and upload the original file.

Many Thanks

From Quito - Ecuador

Michael Dorazio

For those who want to be able to upload a PDF in addition to an image (as I did), do the following:

1) In post_file.php, add 'pdf' to the allowed_ext array
2) In script.js, change the beforeEach function (line 36) to this:

if(!file.type.match(/^image\//) && !file.type.match(/^application\//)){
    alert('Only images and pdfs are allowed!');

    // Returning false will cause the
    // file to be rejected
    return false;
}

3) Also in script.js, in the createImage function, change the reader.onLoad section to this:

reader.onload = function(e){

    // e.target.result holds the DataURL which
    // can be used as a source of the image:
    if (file.type.match(/^application\//)){
        image.attr('src','path/to/your/thumbnail');
    }
    else {
        image.attr('src',e.target.result);
    }
};

where path/to/your/thumbnail is... the path to the image you want to use when someone uploads a pdf.

Note that this might not be too safe since matching "application" allows more than pdf, so any suggestions to improve this are welcome.

Louis Doyle

You could try something like:

file.type == "application/pdf" instead of
Instead of
file.type.match(/^application\//)

Hello and thank you again for this awesome tuto.

By the way, when I try to upload a 60Mb zip file, Chrome crashes (ask me to refresh the page with the "sick" folder icon).

Second issue, for any file I upload (image or zip file), when the progressbar reaches the middle, the upload switches to complete state immediately.

Anyone can confirm this issues too please ?

Config :

  • Chrome 17
  • Windows 7
  • Intel Core i7 with 4GB RAM

Does the same with my home (old) laptop :

  • Chrome 17
  • Windows XP home
  • Centrino 1.6Ghz with 1.5GB RAM
Martin Angelov

For uploading larger files it would probably be better to split them in parts. Currently the entire file is read in memory and this might be causing the problem. Another possible cause might be an upload limit on your server (upload_max_filesize and post_max_size config vars in your php.ini). You can try increasing these settings.

Hi and thanks for the reply.

Well, on the server Max_Upload and Post_Size are both 64MB so it should be fine.

In fact I did some more tests and I've got various issues.
When I upload large files, sometimes Chrome crashes (as decribed above), sometimes server returns me an error 500.
I'm probably experiencing a server issue due to max_execution_time setting (120s), but I have to dig a little bit more on that.

By the way, to go further with your tutorial, I've updated the jQuey FileDrop plugin with the latest version (https://github.com/weixiyen/jquery-filedrop) that handles file queueing (next file starts after previous is done) !
Works well, except when you do multiple drops at the same time... (they still start in parallel).
I've worked on the plugin to fix that case, and have a beginning of answer.
If someone is interested I can share the modified file when it's fully ready.

Cya !

I would like to see that code when ready!

Can you share the modified.
We have same problem.
Thanks !

Hi y(oYo). I have the same problem. Chrome crash when i try to upload a file bigger than 20 mb. Is there some way to fix this problem? I always need to upload file like 120mb each one.
Thank you

Vladimir

Hello, with your script i have made a gallery image hosting
http://picabox.net/
Looks nice, thank you!

i am not able to do it like you did please suggest the way out.
i downloaded your scripts but not working, should i make changes in post_file.php too..? if yes wat are they..??

thanks in advance

Anyway to know when all queued files are complete instead of just each one individually?

beautiful design

This is useful for those who know PHP but what about people like us who work on c#.net. Kindly help us out. I loved your work but do not know how to integrate in asp.net.

Hello,

This works on my laptop which has Windows 7 on it, using Chrome.

But when I use another computer with Vista or Xp it doesn't work. It acts like it does but really all it does is pull up the image, the path to it. Any idea?

i want to let the users upload zips, doc, docx, all known image files and so on (maybe all file extensions how ever)

how can i do this?

my files won't be uploaded

btw: very nice and great tut !

Cristian Rusu

Hello

I amusing this JQuery plugin since a while and I am wondering how can I also add a button to the page to select the files as an alternative to drag-drp... I don't mean to use old way of uploading, just an alternative so I can still see the files after I select them in the drop area and upload progress as if I have them dropped there.

Any clue?
Thanks

Hello

Does anyone know how to add a search button as well as drag'n'drop? (And drag from the result of search)

I've try to add a input type=file, but don't work the drag.
How i can trigger the insert in queue on change if input?

Thanks in advance!

Any way to output the link to the image uploaded ?

would be nice too , curently i passe a data image throu a POST in hidden input

How can I do to display the percentage of load file?

Any way to get this to work in Opera?

Hi,
I need to even think about what the user knows what it take and put the file. It somehow just cause standard file selection by clicking on the dropbox. Something like a drop images here to upload and click or select.

Thanks so much for the advice P

Uncaught SyntaxError: Unexpected token / jquery-1.6.3.min.js:2
e.extend.parseJSON jquery-1.6.3.min.js:2
xhr.onload filedrop.js:223

that's my problem.. how to fix?

I have the uploader working just as it does in the Demo. Problem is that it never writes to the .uploads folder. I have 100% control over the entire server and have even gone so far as to give Full control to everyone on the /uploads folder just for testing.

I get nothing even though the page is displaying a completed status. almost as if it is running in Demo mode, but i have check the Demo Mode flag to insure that it is not running in Demo Mode.

Any Suggestions?

Tim Hershberger

This is an awesome script, thank you. I have it working great. One quick question, how do I make it so the cache is cleared each time the user enters this.

Currently I have it so a client can upload different set of pictures but when they go back to this upload tool they see their previous uploads already loaded in the upload box. Ideally when they leave and click upload (they have 60+ pics) I need to make it so they are automatically deleted from the upload box...or maybe make it so there is a clear all button so they can start a new batch.

Any ideas?

thanks

Is there a way to make the images sent via email instead of storing them on the site? The issue is that we will have several clients using this same upload link

I was wondering, is it possible to display a text box for each individual photo uploaded? To add a caption to the picture if you will... or perhaps just redirect to a page where all these images are in table where you can adjust title and such..?

Heapstore

Hello Martin
Nice tutorial and it works great, but a have one question: how can i drag and drop image from the same page (not from my filesystem) to this area? I need it to create page with favourite photos)

Great post! This helped me so much after 2 days of searching...

How to use the rename function in js? What if I need to rename the files before uploading them?

Thanks in advance.

great tutorial!

i was wondering how would i detect a file is being dragged to the browser so that i can change the landing area shape? (like gmail does)

thanks

Thomas Thomassen

Trying out the demo using Windows 8 Release Preview and the demo claim the browser doesn't support HTML5 uploads - which is incorrect. I tried other File API demos With drag and drop in IE10 and they worked - however I prefer jQuery and was looking for a Nice jQuery solution. Why does it claim IE10 doesn't support the File API and DnD?

because IE9 did not Support it and those scripts always take the last final Version as reference

techzombie

Awesome Script! best i have yet seen. Thank u.

Got it modded nice, only one lil thing i am having trouble with.

I want to capture the response back from post.php

uploadFinished:function(i,file,response){
$.data(file).addClass('done');
// response is the JSON object that post_file.php returns
alert('response from post.php= ' + response //this does not work?
}

How do we capture back the response? I am sure it is a silly idiotic little thing, but I need help :(

Christophe

Hi,

For those who got problem with "Unexpected character ..."
It's due to the comment on top of the php file. I deleted them and added "<?php", "?>" around the code.

Fixed problem

Hi,

really good work.
I will use this in my new project thanks a lot!

I am using this script on an IIS 7.5 (Server 2k8R2) and i simply can't get it working - it's the 5th (I think) upload script I am using and i still can't get anything to work - the frontend seems to upload the files, json is enabled, max_filesize in php.ini is larger than the filesize, HTTP_STATUS is 200 [OK] and HTTP Response is "Content-Encoding:gzipContent-Length:164Content-Type:text/htmlDate:Sat, 09 Jun 2012 10:22:04 GMTServer:Microsoft-IIS/7.5Vary:Accept-EncodingX-Powered-By:PHP/5.3.10, ASP.NET"

Would be really glad if someone could help me :(

First of all, it's a nice tutorial.
Just one question, I have tried the demo and it works
However, after downloading the files and open it, it doesn't work.

Does something need to be modified so that it can work locally?

You need a server to handle uploaded images sir.

Is it possible to get back an html response instead of a json response? Essentially setting the $.ajax property of 'dataType' to 'html' instead of 'json'.

Thanks!
Raf

techzombie

Is there anyway to change the href in the Upload finished function?

The below does not work because I cannot get the current file url in that function

uploadFinished:function(i,file,response){

                ahrefurl = 'blah.html?id=' + response ;
                fileurl.prop('href',ahrefurl);

}

I can get the file url fine in the below function, but cannot get the response here. :(

function createImage(file){

var preview = fileurl = $('a', preview);

}

I cannot seem to save values between these two functions. Please help. I have tried everythng. This is the last thing I need to finish a HUGE project.

Can anyone help me adapt the code to upload videos as well? I'ma beginner.

Can you tell me how to set maxfiles to only one..please tell me the all changes which i should make...please please reply soon....thanks in advance..

Hi,
I had the problem that was discussed here regarding the "JSON.parse: unexpected character"
I fixed it by adding the uploads directory manually.
Martin, thanks for the great code - any upgraded expected soon?
Thanks
Orly

instead of file is there a way i can drag drop my mail from outlook ? if so can u help me out??

Figured it out. You're not sending file-type with the file. I have to check for ext by exploding. Sorry for bugging you. Wasted a lot of time on this....

I got everything working, however, I'm wondering how I can run a script after ALL uploads are finished, not just run it after each. Thanks

Figured that out too. There's an afterAll() function...

Hi, I wonder how can I add another field, I mean, I send with this code a $_FILE[pic] but if I want to sent $_FILE[pic] and $_POST['other thing'] "like an ID", Thanks

Victoria Wagman

Hi!

Awesome script. One thing that I believe is crucial to address is the fact that if someone uploads a file, with the same name as a file which already exists, then that file is replaced. I'm making a page where people can add images of their office spaces, and I'm positive that out of those who bother with the file name, many will choose the same. I'm not sure whether I will try to add a time stamp to the image file or what I should do, but I just wanted to mention this issue.

:)

Victoria Wagman

I added a timestamp in front of every image:

$timestamp = date('Y-m-j_H-i');

if(move_uploaded_file($pic['tmp_name'], $upload_dir.$timestamp."-".$pic['name'])){

Thank you! This works perfectly for those who have a camera using a simple naming system, like 001.jpg that resets when the card is cleared.

The plugin is great, as a developer I don't want to mess around with low-level building HTTP requests. The UI used in this article is fantastic as well - showing the image immediately with a beautiful progressbar. Superb.

I've ported your PHP script to ASP.NET MVC and made some improvements as well. I added support for handling internal server errors and validation messages thrown by server. Think of simple things such as the file already exists, the script does not have permissions to write to the folder and the file was not uploaded correctly (data loss can occur). I also added a .error CSS class for communicating to the user that something went wrong during the upload of such an image. This class has a red transparent background instead of white.

Perhaps you like those improvements as well, they're not hard to implement. I love them ;-)

Amazing Tutorial. Thanks!

I was just wondering - is there a way to clear the queue of images (images downloaded) so that a user can start uploading again... obviously without refreshing the browser...

Thanks!

Great tutorial. I modified a bit to resize photos on upload--works great! However, all my portrait photos are automatically rotated to landscape on upload. Anyone else experiencing this?

Since the 'get_extension' function is still in your script and seems to be quite popular on the web.. thought I should share some other helpfull goodness.

With pathinfo: http://www.php.net/manual/en/function.pathinfo.php, you could extract the name and file extension in one go.

For the extension only you can use: substr(strrchr($pic['name'], '.'), 1);

(strrchr finds last occurence of the dot, so you take the substring of the end of a string minus one character - the dot itself)

But it's a nice blog post

Great tutorial! Thanks for the work.

I only wanted to know if is there any way to trigger the filedrop from an file input type, like

<input type="file" onchange="dropbox.filedrop(fileSelected)" />

in order to load the file selected with the file dialog the same way as if it were dropped down into the box.

Thanks!

Zachary Young

What do I need to call to get the URL of the image upload so that I can put that in the loop, thus allowing uploaded images to directly link to their source URL?

Example: Image finishes uploading, user clicks image, image link takes you to the uploaded image's url.

Thanks, great script!

MrAtiebatie

I really doesn't work for me I've tried to let it work for like 3 days but it just doesn't work :(
It probably don't reach the post_file.php file because when I add an die('hi!'); rule, I don't get it in my browser.

What am I doing wrong?

Commandrea

Lovely! Thank you! And for those don't read through the comments before asking a question, do! Many of the resolutions have been addressed.

James Dinsdale

Hi,

I've had a look through the comments and seen a couple of other people with the same problem. I know I need to call move_uploaded_file, but have no idea how to do this. Can anyone help?

Many Thanks,

James

How do we log all these uploads?

christophe

can i upload one file at the time?

Hey!

really great tutorial. It helped me create a fine upload manager. So thank's a lot.

But i'm still having some difficulties with uploading files with unicode characters in the filename. It works on all tested browsers except for Firefox on Mac. If I drop a file with german special characters like "ä ö ü ß", the upload just does not start.

I tested it with Windows IE,Firefox,Chrome, and also with Mac Safari. All work. Only Firefox on Mac has difficulties.

My Website completely runs on UTF-8. HTML charset is set to UTF-8, PHP and MySQL connections run on UTF-8 and also all Script files are encoded in UTF-8. I really can't find a solution. Any suggestions?

Hey Ric,

file uploads will be done by using "Content-Type: multipart/form-data;" encoded sending of each(!) field.

While usually each Ajax request is encoded by default as UTF8, it seems that posts of this contenttype are NOT sent with UTF8.

My problem was, that database Inserts into UTF8-tables got truncated at the first german-Umlaut (äöü).

Simple trick:
$filename = utf8_encode($_FILES["pic"]["name"]);

Do this with the remaining fields you also post along with the file upload and you will be successful.

My question would be here, if it would be possible (and compatible to existing browsers!) to post additional parameters (e.g. input fields) UTF8-encoded, while sending the file upload binary?

Regards,
Michael :)

Benjamín Spencer

Just delete this in the script.js file:
Line 37

if(!file.type.match(/^image\//)){
alert('Only images are allowed!');

            // Returning false will cause the
            // file to be rejected
            return false;
        }

And then you could upload anything you want

works like a charm. thnks for this one

Can anyone help me on figuring out why this crashes when I dragNdrop a mp4 video file that is 200MB?

I've already changed the file type limitation to accept them.
I'd really appreciate the help.
I'm using chrome.

The script works great. Just one thing, the following scenario allows users to totally bypass the maxfiles rule/validation:

1) Set maxfiles to say 10
2) Drop in 9 files
3) Then drop in 2 more files (which will total 11 files, 1 more than allowed!)

^^^ Currently this is allowed by the script, yet it should be stopped by the maxfiles validation. The only time the maxfiles validation works is when a single drop exceeds what maxfiles has been set to. The validation should work based off a count of existing uploads + the amount of additional files that are attempting to be added to the drop zone.

Any thoughts on how to overcome this Martin?

Vijeet Deliwala

Hello,Nice Tutorial.....

But have you noticed that it has stopped working suddenly since last 2-3 days..............I am using Chrome and Windows 7 and everything was good before........But now,just not able to drag anything............Wondering what may be the problem...

So, say you wanted multiple drop areas, and only one file per area....

Anyone know how to go about that? I'm new to jquery!

Qaysar Akbar

Hello,

Nice tutorial I was wondering if uploading to database feature can be added with the option to allow users to upload manually via a select button in case they are not up to date with technology.

Thanks

After checking the file extension in your php script, you should return an error code if it's invalid and handle the error from the client side. Currently this is not done. This means that you can upload a .jpg file renamed to .bmp, which is shown in the browser but is not processed on the server side.

Logo Quiz Game

Hi,

I'm trying to place 2 drop targets on the same page, and I'm having trouble with the code calling the wrong drop target. Is it limited to only one per page? If not, how can I implement two drop targets on the same page?

Thanks in advance,

Benyamin.

Léon Pelletier

I if you open jquery.filedrop.js and you change the place where drag functionalities are binded to something like this, it should work. Not sure, though. I'm just starting with this uploader.

$(".dropzones").each(function (){
    $(this).bind('drop', drop).bind('dragenter', dragEnter)
           .bind('dragover', dragOver).bind('dragleave', dragLeave);                        
});             

$(document).bind('drop', docDrop).bind('dragenter', docEnter)
       .bind('dragover', docOver).bind('dragleave', docLeave);
albumMan

I have just installed IE10 on Windows 7 and
receive the message "Your browser does not support html5 file upload."
I get the same message on Mac OS10.5 using Safari 5.06

Is there a work around to solve this???

mulscully

I also can not get it to work in IE10.. Any ideas??

In this plugin any way set minimum height width limit

Thanks

I am hoping you can help me understand why this is not working.

I have implemented your code into my website and it is working fine the files get uploaded to the directory but I need to make one change and it is not working. I want to change the uploaded file name to a php variable $petitionid set when the page is first loaded but the variable ends up being empty when it runs the following code in your post_file.php so I end up getting a file name of _banner.jpg

I am assuming this has something to do with that the php file is being called from javascript so the variables on the original page our out of scope? Any idea how I can get the information from this variable on the original page?

// Move the uploaded file from the temporary 
// directory to the uploads folder:

if(move_uploaded_file($pic['tmp_name'], $upload_dir.$petitionid.&quot;_banner.&quot;.get_extension($pic['name']))){
    exit_status('File was uploaded successfuly!');
}

Hi,
i used your code and it working fine with the url set as "url: 'post_file.php'," but when i replaced the url location with
url: '<?php echo site_url('media/upload_featureimage');?>',
which is the controller/function_name, enabling the file upload in CI....it doesn't work! The progress stops in the middle and the file is not getting uploaded!

hi
thanks for this instruction.
I have a problem.When I drag the image into the box, uploaded.. But there is no link to download.How can this feature be added?
When you upload a photo, the address should be to download.
thanks

Marian Stevens

I am wanting to integrate this with MySQL as well - I need some form fields on the page to capture information about the photos being uploaded, and it seems obvious to ID them for selecting the values() in jQuery and passing that to the php handler form which can parse everything and make entries into the database as well as handle the uploads - but I'm not sure where my starting point is in passing extra form fields as I don't see a DataString jumping out at me to send the info via AJAX. I'd appreciate any suggestions.

I had been using Uploadify but my hosting company shut it down with security issues. This seems to handle security/file size issues as well as file types. I had covered file types when I modified Uploadify but I also need to get away from Flash completely and Uploadify relied on Flash.

Hi,
Congratulations for the tutorial, I have the following problem once the image is placed in the charging up to 50% and through the console I display the following message:

ArrayBuffer is deprecated in XMLHttpRequest.send(). Use ArrayBufferView instead. jquery.filedrop.js:311
XHR finished loading: "http://clubprive.netsons.org/upload.php&quot;. jquery.filedrop.js:311
XMLHttpRequest.sendAsBinary jquery.filedrop.js:311
send

How can I fix the problem?

bob bronkxs

This is awesome! I had it working a treat within 5 minutes! Since then i have re-looked over it all and my website just uses the scripts now lol.

A lot of users who have asked comments on here really need to re-read other peoples previous comments as they answer all the questions anyways:/

Great job on this tutorial if you could improve on actually linking people to their image after their upload is a success and add maybe even blanked out examples in the scripts of how people can add other extensions it would be a better improvement. But this is really kool and a good job well done mate. +1.

Jeferson Nunes Jaconetti

I downloaded the demo, but isn't working. The upload stopped in the middle and don't show me any message. What can I do? Thank's.

Just wanted to give an example of how you can integrate this into a symfony 2 project.

I had to modify the JS script to add the file field to mimic a symfony 2 form, and add the '_token' field in to pass the csrf check.

So my JS uses the paramname of 'file[file]' to add the uploaded file into the file array expected by symfony forms, and add the data attribute like so:

data: {
"file[_token]": $('#file__token').val()
},

this then will pass the $form->handleRequest($request); method. This can then be referenced with: $request->files->get('file');

I hope this helps someone out.

readAsBinaryString has been depreciated.

Bert Oost

Filedrop is great! Only (at least) the finish callback does the $.parseJSON already.
I think it's not up to Filedrop to assume JSON is being returned from the ajax request. It should just pass the responseText from the call and not assume it's a JSON format. This should be up to the end user (we! the developers! hehe).

Hey, this is working great,
thank you! You wouldn't believe how hard it is to actually find such an easy and well described solution for something that people will really use in a variety of ways!
Do you know how to change this so it works for a smartphone as well? I am not a big coder.
I guess I would need the upload button and also as you said above "code to display the images"? I won't be able to do that.
But do you know of something like a "smartphone upload center"?
Thanks in advance
Chris

Is there a way, after the image has Uploaded to the server, and inserted the data into the database, to have its record ID sent back to the page, and shown in a Form field?

Also, to have a random Number generated for each of the images, so that it can be looped in the update?

The reason why I need this.
Is to have the ability to edit the image properties on the same page that the images are uploaded from.
Like what Facebook is doing on their upload script.

If this is not a possibility, then is there a way to do a redirect to a page for editing, after it has uploaded all the images?

Any idea's on this, would be great.
Wayne