javascript - How can I upload files asynchronously with jQuery?

ID : 184

viewed : 141

Tags : javascriptjqueryajaxasynchronousxmlhttprequestjavascript

Top 5 Answer for javascript - How can I upload files asynchronously with jQuery?

vote vote

99

With HTML5 you can make file uploads with Ajax and jQuery. Not only that, you can do file validations (name, size, and MIME type) or handle the progress event with the HTML5 progress tag (or a div). Recently I had to make a file uploader, but I didn't want to use Flash nor Iframes or plugins and after some research I came up with the solution.

The HTML:

<form enctype="multipart/form-data">     <input name="file" type="file" />     <input type="button" value="Upload" /> </form> <progress></progress> 

First, you can do some validation if you want. For example, in the .on('change') event of the file:

$(':file').on('change', function () {   var file = this.files[0];    if (file.size > 1024) {     alert('max upload size is 1k');   }    // Also see .name, .type }); 

Now the $.ajax() submit with the button's click:

$(':button').on('click', function () {   $.ajax({     // Your server script to process the upload     url: 'upload.php',     type: 'POST',      // Form data     data: new FormData($('form')[0]),      // Tell jQuery not to process data or worry about content-type     // You *must* include these options!     cache: false,     contentType: false,     processData: false,      // Custom XMLHttpRequest     xhr: function () {       var myXhr = $.ajaxSettings.xhr();       if (myXhr.upload) {         // For handling the progress of the upload         myXhr.upload.addEventListener('progress', function (e) {           if (e.lengthComputable) {             $('progress').attr({               value: e.loaded,               max: e.total,             });           }         }, false);       }       return myXhr;     }   }); }); 

As you can see, with HTML5 (and some research) file uploading not only becomes possible but super easy. Try it with Google Chrome as some of the HTML5 components of the examples aren't available in every browser.

vote vote

87

2019 Update: It still depends on the browsers your demographic uses.

An important thing to understand with the "new" HTML5 file API is that it wasn't supported until IE 10. If the specific market you're aiming at has a higher-than-average propensity toward older versions of Windows, you might not have access to it.

As of 2017, about 5% of browsers are one of IE 6, 7, 8 or 9. If you head into a big corporation (e.g., this is a B2B tool or something you're delivering for training) that number can skyrocket. In 2016, I dealt with a company using IE8 on over 60% of their machines.

It's 2019 as of this edit, almost 11 years after my initial answer. IE9 and lower are globally around the 1% mark but there are still clusters of higher usage.

The important take-away from this —whatever the feature— is, check what browser your users use. If you don't, you'll learn a quick and painful lesson in why "works for me" isn't good enough in a deliverable to a client. caniuse is a useful tool but note where they get their demographics from. They may not align with yours. This is never truer than enterprise environments.

My answer from 2008 follows.


However, there are viable non-JS methods of file uploads. You can create an iframe on the page (that you hide with CSS) and then target your form to post to that iframe. The main page doesn't need to move.

It's a "real" post so it's not wholly interactive. If you need status you need something server-side to process that. This varies massively depending on your server. ASP.NET has nicer mechanisms. PHP plain fails, but you can use Perl or Apache modifications to get around it.

If you need multiple file uploads, it's best to do each file one at a time (to overcome maximum file upload limits). Post the first form to the iframe, monitor its progress using the above and when it has finished, post the second form to the iframe, and so on.

Or use a Java/Flash solution. They're a lot more flexible in what they can do with their posts...

vote vote

79

I recommend using the Fine Uploader plugin for this purpose. Your JavaScript code would be:

$(document).ready(function() {   $("#uploadbutton").jsupload({     action: "addFile.do",     onComplete: function(response){       alert( "server response: " + response);     }   }); }); 
vote vote

60

Note: This answer is outdated, it is now possible to upload files using XHR.


You cannot upload files using XMLHttpRequest (Ajax). You can simulate the effect using an iframe or Flash. The excellent jQuery Form Plugin that posts your files through an iframe to get the effect.

vote vote

54

Wrapping up for future readers.

Asynchronous File Upload

With HTML5

You can upload files with jQuery using the $.ajax() method if FormData and the File API are supported (both HTML5 features).

You can also send files without FormData but either way the File API must be present to process files in such a way that they can be sent with XMLHttpRequest (Ajax).

$.ajax({   url: 'file/destination.html',    type: 'POST',   data: new FormData($('#formWithFiles')[0]), // The form with the file inputs.   processData: false,   contentType: false                    // Using FormData, no need to process data. }).done(function(){   console.log("Success: Files sent!"); }).fail(function(){   console.log("An error occurred, the files couldn't be sent!"); }); 

For a quick, pure JavaScript (no jQuery) example see "Sending files using a FormData object".

Fallback

When HTML5 isn't supported (no File API) the only other pure JavaScript solution (no Flash or any other browser plugin) is the hidden iframe technique, which allows to emulate an asynchronous request without using the XMLHttpRequest object.

It consists of setting an iframe as the target of the form with the file inputs. When the user submits a request is made and the files are uploaded but the response is displayed inside the iframe instead of re-rendering the main page. Hiding the iframe makes the whole process transparent to the user and emulates an asynchronous request.

If done properly it should work virtually on any browser, but it has some caveats as how to obtain the response from the iframe.

In this case you may prefer to use a wrapper plugin like Bifröst which uses the iframe technique but also provides a jQuery Ajax transport allowing to send files with just the $.ajax() method like this:

$.ajax({   url: 'file/destination.html',    type: 'POST',   // Set the transport to use (iframe means to use Bifröst)   // and the expected data type (json in this case).   dataType: 'iframe json',                                   fileInputs: $('input[type="file"]'),  // The file inputs containing the files to send.   data: { msg: 'Some extra data you might need.'} }).done(function(){   console.log("Success: Files sent!"); }).fail(function(){   console.log("An error occurred, the files couldn't be sent!"); }); 

Plugins

Bifröst is just a small wrapper that adds fallback support to jQuery's ajax method, but many of the aforementioned plugins like jQuery Form Plugin or jQuery File Upload include the whole stack from HTML5 to different fallbacks and some useful features to ease out the process. Depending on your needs and requirements you might want to consider a bare implementation or either of this plugins.

Top 3 video Explaining javascript - How can I upload files asynchronously with jQuery?

Related QUESTION?