I would like to upload a file asynchronously with jQuery. This is my HTML:

<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>

And here my Jquery code:

$(document).ready(function () {
    $("#uploadbutton").click(function () {
        var filename = $("#file").val();

        $.ajax({
            type: "POST",
            url: "addFile.do",
            enctype: 'multipart/form-data',
            data: {
                file: filename
            },
            success: function () {
                alert("Data Uploaded: ");
            }
        });
    });
});

Instead of the file being uploaded, I am only getting the filename. What can I do to fix this problem?

Current Solution

I am using the jQuery Form Plugin to upload files.

67 upvote
  flag
you are only getting the file name because your var filename is getting the value of $('#file'), not the file that lies in the input – Jimmy
20 upvote
  flag
Here's a good one: http://blueimp.github.io/jQuery-File-Upload/ - HTML5 ajax uploading - Graceful fallback to iframes for unsupported browsers - Multi-file async upload We've used it and it works great. (Documentation here) – Ashish Panery
upvote
  flag
jQuery Form Plugin seems the most simple-to-use and cross-browser compatible way... am I right ? – Lyth
3 upvote
  flag
Check also this: //allinonescript.com/questions/6974684/…, here it explains how to achieve it via jQuery – Chococroc
1 upvote
  flag
@Jimmy How would he get the get the file that lies in the input instead? – alex
upvote
  flag
If I write the above code, I am getting: POST localhost:9000/upload 500 (Internal Server Error) – Dhana
upvote
  flag
Refer this for fully working answer - //allinonescript.com/a/15327377/1362713 – M_R_K
upvote
  flag
You can try to check this for a full working example and demo whats-online.info/science-and-tutorials/30/… – Daniel Nyamasyo

25 Answers 11

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. Try the SWF (Flash) uploader SWFUpload.

Or the excellent jQuery Form Plugin that posts your files through an iframe to get the effect.

1 upvote
  flag
Yes, you can POST to an iframe and capture the file there. I have very limited experience with this though, so I can't really comment on it. – Mattias
14 upvote
  flag
Small remark: in latest versions of chrome and firefox it is possible, //allinonescript.com/questions/4856917/… – Alleo

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

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

Going into 2017, about 5% of browsers are one of IE 6, 7, 8 or 9. If you head into a big corporation (eg this is a B2B tool, or something you're delivering for training) that number can rocket. Just a few months ago —in 2016— I dealt with a company using IE8 on over 60% of their machines.

So before you do anything: 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.

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...

136 upvote
  flag
For the record it's now possible to do pure AJAX file uploads if the browser supports the File API - developer.mozilla.org/en/using_files_from_web_applications – meleyal
32 upvote
  flag
Unless you need IE9 support. caniuse.com/fileapi – Oli
upvote
  flag
iframe solution is pretty simple and easy to get working – Matthew Lock
upvote
  flag
this is quite an old answer, but it was a bit misleading.. IE supported XHR natively as far back as IE7, and supported it through ActiveX as far back as IE5. w3schools.com/ajax/ajax_xmlhttprequest_create.asp. The practical way of doing this was certainly targeting flash (shockwave) components, or rolling out a Flash/ActiveX (Silverlight) control. If you can originate a request and handle the response via javascript, it's ajax.. though, having said that, ajax is synonymous with xhr, but it doesn't itself describe the underline mechanism/components that delivers/exchanges the payload. – Brett Caswell
4 upvote
  flag
@BrettCaswell I wasn't saying that AJAX/XHR weren't possible, just that it wasn't possible to post a file up with them on old —but everliving— versions of IE. That was and remains completely true. – Oli

There are various ready-made plugins on doing file upload for jQuery.

Doing this kind of uploading hacks is not an enjoyable experience, so people enjoy using ready-made solutions.

Here's few:

You can search for more projects on NPM (using "jquery-plugin" as the keyword) or on Github.

14 upvote
  flag
The AjaxFUP-link seems to be broken. I suspect this is what is refered to: valums.com/ajax-upload – UlfR
1 upvote
  flag
For yet another read-made plugin, there's always Filepicker.io, which is kind of nice in that it deals with all of the nasty large file support issues, etc. – brettcvz
8 upvote
  flag
It's actually only about 10 lines of vanilla JS. It really isn't so bad. – mpen
3 upvote
  flag
Ready-made solution plugins may work great but it doesn't help after a while you find out it doesn't work you thought it would and you had to hack it with unfamiliar scripts. So, it goes both ways. – fletchsod
upvote
  flag
Can i use JQuery File Uploader for multiple videos..? will it support..? – Mr world wide

A solution I found was to have the <form> target a hidden iFrame. The iFrame can then run JS to display to the user that it's complete (on page load).

upvote
  flag
This is what jQuery Form does: malsup.com/jquery/form – Darryl Hein
1 upvote
  flag
i am interested in this answer, do you have a demo you can link to? – lfender6445

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);
    }
  });
});
upvote
  flag
It uses JSON - so for PHP old version it will be non possible use. – Lorenzo Manucci
upvote
  flag
Seems much cleaner than Ajax File Upload, where I need to include a huge piece of code just to use the damn thing. – ripper234
5 upvote
  flag
upvote
  flag
Newer URL for version 2 is now valums-file-uploader.github.com/file-uploader – Simon East
34 upvote
  flag
"This plugin is open sourced under GNU GPL 2 or later and GNU LGPL 2 or later." So as long as you don't distribute the copy or a modified version, you don't have to open your project. – Trantor Liu
upvote
  flag
Am I missing something? This library doesn't seem to use jquery any more, so it doesn't support the syntax from the answer? – James McCormack
upvote
  flag
@Kerry Do you have a link regarding MIT license? The latest version (Version 4) appears to be GPL3 only, no LGPL: github.com/Widen/fine-uploader#license Version 2 mentions LGPL: valums-file-uploader.github.io/file-uploader – Darren Cook
upvote
  flag
@DarrenCook Yeah, I noticed that earlier this year. I have a downloaded copy of the old code, not as pretty, but it still has the old license, but not online. – Kerry Jones
1 upvote
  flag
This is the website (fineuploader.com) I found now, it's V4.2 . – Andrew_1510
upvote
  flag
@BryanLarsen You do not need to release the code if it is a website (or a SaaS solution), since you are not distributing the "binary", you do not need to distribute the code. Some resources : //allinonescript.com/questions/3701011/… – Ankan-Zerob
upvote
  flag
They have switched license again. it's a proprietary license that separately calls out commercial use, so unlike the GPL, there is no escape from licensing the latest version for commercial use. This is the last committed version available under GPL (Dec 2014). – Oli
upvote
  flag
As of Fine Uploader 5.9.0, the library is now 100% Free Open Source Software and MIT licensed. – Ray Nicholus

I've written this up in a Rails environment. It's only about five lines of JavaScript, if you use the lightweight jQuery-form plugin.

The challenge is in getting AJAX upload working as the standard remote_form_for doesn't understand multi-part form submission. It's not going to send the file data Rails seeks back with the AJAX request.

That's where the jQuery-form plugin comes into play.

Here’s the Rails code for it:

<% remote_form_for(:image_form, 
                   :url => { :controller => "blogs", :action => :create_asset }, 
                   :html => { :method => :post, 
                              :id => 'uploadForm', :multipart => true }) 
                                                                        do |f| %>
 Upload a file: <%= f.file_field :uploaded_data %>
<% end %>

Here’s the associated JavaScript:

$('#uploadForm input').change(function(){
 $(this).parent().ajaxSubmit({
  beforeSubmit: function(a,f,o) {
   o.dataType = 'json';
  },
  complete: function(XMLHttpRequest, textStatus) {
   // XMLHttpRequest.responseText will contain the URL of the uploaded image.
   // Put it in an image element you create, or do with it what you will.
   // For example, if you have an image elemtn with id "my_image", then
   //  $('#my_image').attr('src', XMLHttpRequest.responseText);
   // Will set that image tag to display the uploaded image.
  },
 });
});

And here’s the Rails controller action, pretty vanilla:

 @image = Image.new(params[:image_form])
 @image.save
 render :text => @image.public_filename

I’ve been using this for the past few weeks with Bloggity, and it’s worked like a champ.

I've come across a few really powerful jQuery-based file upload libraries. Check these out:

  1. Plupload
  2. jQuery File Upload
  3. FineUploader

This AJAX file upload jQuery plugin uploads the file somehwere, and passes the response to a callback, nothing else.

  • It does not depend on specific HTML, just give it a <input type="file">
  • It does not require your server to respond in any particular way
  • It does not matter how many files you use, or where they are on the page

-- Use as little as --

$('#one-specific-file').ajaxfileupload({
  'action': '/upload.php'
});

-- or as much as --

$('input[type="file"]').ajaxfileupload({
  'action': '/upload.php',
  'params': {
    'extra': 'info'
  },
  'onComplete': function(response) {
    console.log('custom handler for file:');
    alert(JSON.stringify(response));
  },
  'onStart': function() {
    if(weWantedTo) return false; // cancels upload
  },
  'onCancel': function() {
    console.log('no file selected');
  }
});
4 upvote
  flag
Not working with 1.9.1 :| – user840250
1 upvote
  flag
@user840250 jQuery 1.9.1? – Jordan Feldstein

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 onChange 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.

upvote
  flag
How do return data from the file that the file was posted to? – Dan
1 upvote
  flag
@Silver89 if you mean to return data from the server script you set in the url setting('upload.php' in this case), the response will be whatever you print or echo in that script. Then you can do whatever you want with the data. Check the ajaxComplete and similar functions in jQuery Docs – olanod
3 upvote
  flag
I have the file part working ... but can you include text fields in this as well? This doesn't seem to with var formData = new FormData($('form')[0]); or serialize() ? – Dan
upvote
  flag
with "new FormData($('form')[0]);" it should work, your text field has a name? use print_r on $_POST to make sure data is there, check the response on the network monitor(chrome) to see the raw response. – olanod
9 upvote
  flag
Can I then use $_FILES in the upload.php? – Alessandro Cosentino
67 upvote
  flag
This should work in Internet Explorer but only Version 10. (caniuse.com/xhr2) – Samir
123 upvote
  flag
Doesn't work in IE7-9 – KevinDeus
1 upvote
  flag
Awesome answer! Minor edit: should have var keyword to scope myXhr variable in third code snippet. – Zugwalt
16 upvote
  flag
Hi, I appreciate PHP is your language of choice... but I am wondering if you know if this also works in ASP.NET MVC? I am a .NET developer and I have tried to utilize your simple example to do some AJAX file uploading but server side I do not get the file I posted via AJAX. I am using latest Chrome. – Shumii
upvote
  flag
Can i use upload in $('input:file').change()? I'm trying, but I have zero-sized $_FILES and $_POST in php script – indapublic
1 upvote
  flag
@olanod is it possible to upload more data with this? – RyanDawkins
18 upvote
  flag
It's FormData who does all the magic here. Be sure to check these docs — it covers all your question about multiple files and fields. – incarnate
upvote
  flag
This doesn't appear to work with jquery. I cannot pass a FormData object to .ajax() as the data setting is either type PlainObject or String. I have to be missing something if this broken example got 775 votes. – Alex Barker
1 upvote
  flag
do you need to write contentType: false? – think123
upvote
  flag
Although I love this, I still feel its not complete. I designed our AJAX to upload the file in chunks, and although it tends to upload load a bit more than, its a lot more robust, and also allows the user to "pause" and "resume/retry" uploads. – Rahly
1 upvote
  flag
first of all thank's to share it.. but please can any one tell me how to handle this file in 'upload.php' to process it. – Code_Crash
1 upvote
  flag
@olanod Hello sir. thanks for this . please can you tell me how to handle this file in upload.php – Code_Crash
2 upvote
  flag
For those interested: In Aspnetmvc the server code is as simple as public ActionResult Upload() { var files = Request.Files ... – LosManos
upvote
  flag
I am using .net and copy pasted js. I dont see anything posted either Request.Files or Request.Form. What should I do? – hakan
upvote
  flag
How to handle <input name="file" type="file" multiple="multiple"/> here? Thank you. – user12458
upvote
  flag
I know its been a while since a comment on this but I am using this example and for some reason my php file is returning a black array when I use print_r($_POST) – Cesar Bielich
upvote
  flag
How to send Post request with FormData() in IE 10.0.9200 ? – Mohit Kumar Gupta
upvote
  flag
@olanod i asked a similar question can you check it and give an answer?//allinonescript.com/questions/28644200/… – Brownman Revival
upvote
  flag
After XmlHttpRequest, $_FILES["file"]["name"] can't catch the file in server side. What do you suggest me? – Hasan
1 upvote
  flag
Just a minor note: POST requests are never cached, so the cache: false option is redundant here. – Gone Coding
upvote
  flag
Aside from the optional usage of the HTML5 <progress> tag, I don't see any reason HTML5 has so much attention in this answer when good ol' JS and PHP are doing the job themselves... – Deji
upvote
  flag
@Deji, the html5 control <input type="file"> is what is relevant here. the js event handling is provided as to make the uploading of that file (after the user interacts with the control) asynchronous. Infact, you wouldn't need js at all if you submitted the form, but, again, that wouldn't be asynchronous. – Brett Caswell
upvote
  flag
@BrettCaswell But again, that is nothing to do with HTML5. That has existed for donkey's years. – Deji
upvote
  flag
@Deji, ah I see.. it certainly has.. though the behavior seems it may have changed in html5 (vocabulary and associated APIs for HTML and XHTML)[w3.org/TR/html5/forms.html#file-upload-state-(type=fi‌​le)] – Brett Caswell
upvote
  flag
@Deji, hmm, actually.. the doc lists HtmlInputElment [type='file'] was extended, not changed (which makes sense, since we're talking about interfaces here).. w3.org/TR/html5-diff/#other-extensions.. so I guess this answer is applicable to XHTML, and not solely HTML5 (though, the raising of the onchange event may be new in the implementation) – Brett Caswell
3 upvote
  flag
Just so someone else doesn't spend hours... the name="file" is very important on the <input> file tag if you're going to use the data in PHP (and probably other places). I created a form dynamically using javascript so I didn't need the name attribute but found out the hard way you absolutely need it to retrieve the data server-side. – Kivak Wolf
upvote
  flag
Hi @olanod, I have a similar problem, I am not able to pass a file by ajax so that it can be used in Symfony2. can you help me? You can see my question here – Joseph
upvote
  flag
Can you tell me where you call the progress function. I have written a full html5 plugin which does my upload, but not sure how to implement the progress. – Thomas Williams
upvote
  flag
In the block where the xhr object is edited, an event listener for the progress event is added to the xhr.upload object. If you want to do something on progress just apply your logic in the callback passed to that event listener(progressHandlingFunction). – olanod
upvote
  flag
Post sending empty when i upload file more than 250 MB – Davinder Kumar
1 upvote
  flag
its not working – Gowthaman

I have been using the below script to upload images which happens to work fine.

HTML

<input id="file" type="file" name="file"/>
<div id="response"></div>

JavaScript

jQuery('document').ready(function(){
    var input = document.getElementById("file");
    var formdata = false;
    if (window.FormData) {
        formdata = new FormData();
    }
    input.addEventListener("change", function (evt) {
        var i = 0, len = this.files.length, img, reader, file;

        for ( ; i < len; i++ ) {
            file = this.files[i];

            if (!!file.type.match(/image.*/)) {
                if ( window.FileReader ) {
                    reader = new FileReader();
                    reader.onloadend = function (e) {
                        //showUploadedItem(e.target.result, file.fileName);
                    };
                    reader.readAsDataURL(file);
                }

                if (formdata) {
                    formdata.append("image", file);
                    formdata.append("extra",'extra-data');
                }

                if (formdata) {
                    jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');

                    jQuery.ajax({
                        url: "upload.php",
                        type: "POST",
                        data: formdata,
                        processData: false,
                        contentType: false,
                        success: function (res) {
                         jQuery('div#response').html("Successfully uploaded");
                        }
                    });
                }
            }
            else
            {
                alert('Not a vaild image!');
            }
        }

    }, false);
});

Explanation

I use response div to show the uploading animation and response after upload is done.

Best part is you can send extra data such as ids & etc with the file when you use this script. I have mention it extra-data as in the script.

At the PHP level this will work as normal file upload. extra-data can be retrieved as $_POST data.

Here you are not using a plugin and stuff. You can change the code as you want. You are not blindly coding here. This is the core functionality of any jQuery file upload. Actually Javascript.

5 upvote
  flag
-1 for using jQuery and not using it's selector engine and event handlers. addEventListener is not cross-browser. – Marcel
3 upvote
  flag
Because it would be pointless to add a separate answer which would be mostly based on this one, with just a few changes. Instead, this answer should be corrected. – Marcel
2 upvote
  flag
@RainFromHeaven, please, can you edit the answer? I don't know how to do it in the cross-browser way. – Thiago Negri
2 upvote
  flag
Still does not work in IE 9 and down. Allot of users still use those versions of IE. – Pierre
1 upvote
  flag
Can someone please explain how can this be made to work in asp.net? Do I use webmethod? If yes what would it look like? – Arbaaz

You can do it in vanilla JavaScript pretty easily. Here's a snippet from my current project:

var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(e) {
    var percent = (e.position/ e.totalSize);
    // Render a pretty progress bar
};
xhr.onreadystatechange = function(e) {
    if(this.readyState === 4) {
        // Handle file upload complete
    }
};
xhr.open('POST', '/upload', true);
xhr.setRequestHeader('X-FileName',file.name); // Pass the filename along
xhr.send(file);
3 upvote
  flag
@Gary: Sorry, I should have posted that bit too. I was just using the new drag-and-drop functionality in HTML5; you can find an example here: html5demos.com/file-api#view-source -- just click "view source". Essentially, inside the ondrop event you can do var file = e.dataTransfer.files[0] – mpen
upvote
  flag
Perhaps the question has been edited since, but some people on a let's discussion I opened think a vanilla JS answer is off topic if OP asks for a jQuery solution (provided one exists) and such answers belong with a separate question. – Andy
1 upvote
  flag
@Andy Well I disagree, and it seems 34 others do too. If you can use jQuery, then you can certainly use JavaScript. In any case, this is a community site -- it's not just OP that I'm trying to help here. Everyone is free to choose/use the answer they like best. Some people just gravitate towards jQuery because they think it'll be so much easier/fewer lines of code, when really they don't need the overhead of an extra library at all. – mpen

jQuery Uploadify is another good plugin which I have used before to upload files. The JavaScript code is as simple as the following: code. However, the new version does not work in Internet Explorer.

$('#file_upload').uploadify({
    'swf': '/public/js/uploadify.swf',
    'uploader': '/Upload.ashx?formGuid=' + $('#formGuid').val(),
    'cancelImg': '/public/images/uploadify-cancel.png',
    'multi': true,
    'onQueueComplete': function (queueData) {
        // ...
    },
    'onUploadStart': function (file) {
        // ...
    }
});

I have done a lot of searching and I have come to another solution for uploading files without any plugin and only with ajax. The solution is as below:

$(document).ready(function () {
    $('#btn_Upload').live('click', AjaxFileUpload);
});

function AjaxFileUpload() {
    var fileInput = document.getElementById("#Uploader");
    var file = fileInput.files[0];
    var fd = new FormData();
    fd.append("files", file);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", 'Uploader.ashx');
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
             alert('success');
        }
        else if (uploadResult == 'success')
            alert('error');
    };
    xhr.send(fd);
}
2 upvote
  flag
Uploadify has been dead for years. Not supported or maintained anymore. – Ray Nicholus

Simple Ajax Uploader is another option:

https://github.com/LPology/Simple-Ajax-Uploader

  • Cross-browser -- works in IE7+, Firefox, Chrome, Safari, Opera
  • Supports multiple, concurrent uploads -- even in non-HTML5 browsers
  • No flash or external CSS -- just one 5Kb Javascript file
  • Optional, built-in support for fully cross-browser progress bars (using PHP's APC extension)
  • Flexible and highly customizable -- use any element as upload button, style your own progress indicators
  • No forms required, just provide an element that will serve as upload button
  • MIT license -- free to use in commercial project

Example usage:

var uploader = new ss.SimpleUpload({
    button: $('#uploadBtn'), // upload button
    url: '/uploadhandler', // URL of server-side upload handler
    name: 'userfile', // parameter name of the uploaded file
    onSubmit: function() {
        this.setProgressBar( $('#progressBar') ); // designate elem as our progress bar
    },
    onComplete: function(file, response) {
        // do whatever after upload is finished
    }
});
2 upvote
  flag
This seems to be the most promising so far, You had me at IE7+! Trying it out now. Thanks – Pierre

You can use

$(function() {
    $("#file_upload_1").uploadify({
        height        : 30,
        swf           : '/uploadify/uploadify.swf',
        uploader      : '/uploadify/uploadify.php',
        width         : 120
    });
});

Demo

3 upvote
  flag
... which uses the uploadify library, I guess? You should probably state that in your answer. – Zero3

To upload file asynchronously with Jquery use below steps:

step 1 In your project open Nuget manager and add package (jquery fileupload(only you need to write it in search box it will come up and install it.)) URL: https://github.com/blueimp/jQuery-File-Upload

step 2 Add below scripts in the HTML files, which are already added to the project by running above package:

jquery.ui.widget.js

jquery.iframe-transport.js

jquery.fileupload.js

step 3 Write file upload control as per below code:

<input id="upload" name="upload" type="file" />

step 4 write a js method as uploadFile as below:

 function uploadFile(element) {

            $(element).fileupload({

                dataType: 'json',
                url: '../DocumentUpload/upload',
                autoUpload: true,
                add: function (e, data) {           
                  // write code for implementing, while selecting a file. 
                  // data represents the file data. 
                  //below code triggers the action in mvc controller
                  data.formData =
                                    {
                                     files: data.files[0]
                                    };
                  data.submit();
                },
                done: function (e, data) {          
                   // after file uploaded
                },
                progress: function (e, data) {

                   // progress
                },
                fail: function (e, data) {

                   //fail operation
                },
                stop: function () {

                  code for cancel operation
                }
            });

        };

step 5 In ready function call element file upload to initiate the process as per below:

$(document).ready(function()
{
    uploadFile($('#upload'));

});

step 6 Write MVC controller and Action as per below:

public class DocumentUploadController : Controller
    {       

        [System.Web.Mvc.HttpPost]
        public JsonResult upload(ICollection<HttpPostedFileBase> files)
        {
            bool result = false;

            if (files != null || files.Count > 0)
            {
                try
                {
                    foreach (HttpPostedFileBase file in files)
                    {
                        if (file.ContentLength == 0)
                            throw new Exception("Zero length file!");                       
                        else 
                            //code for saving a file

                    }
                }
                catch (Exception)
                {
                    result = false;
                }
            }


            return new JsonResult()
                {
                    Data=result
                };


        }

    }

Convert file to base64 using |HTML5's readAsDataURL() or some base64 encoder. Fiddle here

var reader = new FileReader();

        reader.onload = function(readerEvt) {
            var binaryString = readerEvt.target.result;
            document.getElementById("base64textarea").value = btoa(binaryString);
        };

        reader.readAsBinaryString(file);

Then to retrieve:

window.open("data:application/octet-stream;base64," + base64);

The simplest and most robust way I have done this in the past, is to simply target a hidden iFrame tag with your form - then it will submit within the iframe without reloading the page.

That is if you don't want to use a plugin, JavaScript or any other forms of "magic" other than HTML. Of course you can combine this with JavaScript or what have you...

<form target="iframe" action="" method="post" enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

<iframe name="iframe" id="iframe" style="display:none" ></iframe>

You can also read the contents of the iframe onLoad for server errors or success responses and then output that to user.

Chrome, iFrames, and onLoad

-note- you only need to keep reading if you are interested in how to setup a UI blocker when doing uploading/downloading

Currently Chrome doesn't trigger the onLoad event for the iframe when it's used to transfer files. Firefox, IE, and Edge all fire the onload event for file transfers.

The only solution that I found works for Chrome was to use a cookie.

To do that basically when the upload/download is started:

  • [Client Side] Start an interval to look for the existence of a cookie
  • [Server Side] Do whatever you need to with the file data
  • [Server Side] Set cookie for client side interval
  • [Client Side] Interval sees the cookie and uses it like the onLoad event. For example you can start a UI blocker and then onLoad ( or when cookie is made ) you remove the UI blocker.

Using a cookie for this is ugly but it works.

I made a jQuery plugin to handle this issue for Chrome when downloading, you can find here

https://github.com/ArtisticPhoenix/jQuery-Plugins/blob/master/jQuery-Plugins/iDownloader.js

The same basic principal applies to uploading, as well.

To use the downloader ( include the JS, obviously )

 $('body').iDownloader({
     "onComplete" : function(){
          $('#uiBlocker').css('display', 'none'); //hide ui blocker on complete
     }
 });

 $('somebuttion').click( function(){
      $('#uiBlocker').css('display', 'block'); //block the UI
      $('body').iDownloader('download', 'htttp://example.com/location/of/download');
 });

And on the server side, just before transferring the file data, create the cookie

 setcookie('iDownloader', true, time() + 30, "/");

The plugin will see the cookie, and then trigger the onComplete callback.

3 upvote
  flag
I love it. If only someone could mention the potential problems with this brilliant solution. I really don't understand why people wright and use these clunky libraries and plugins when there is the solution. – Yevgeniy Afanasyev
1 upvote
  flag
Well, I guess the reason would be to show some progress info while uploading. – Prakhar Mishra

You can upload simply with jQuery .ajax().

HTML:

<form id="upload-form">
    <div>
        <label for="file">File:</label>
        <input type="file" id="file" name="file" />
        <progress class="progress" value="0" max="100"></progress>
    </div>
    <hr />
    <input type="submit" value="Submit" />
</form>

CSS

.progress { display: none; }

Javascript:

$(document).ready(function(ev) {
    $("#upload-form").on('submit', (function(ev) {
        ev.preventDefault();
        $.ajax({
            xhr: function() {
                var progress = $('.progress'),
                    xhr = $.ajaxSettings.xhr();

                progress.show();

                xhr.upload.onprogress = function(ev) {
                    if (ev.lengthComputable) {
                        var percentComplete = parseInt((ev.loaded / ev.total) * 100);
                        progress.val(percentComplete);
                        if (percentComplete === 100) {
                            progress.hide().val(0);
                        }
                    }
                };

                return xhr;
            },
            url: 'upload.php',
            type: 'POST',
            data: new FormData(this),
            contentType: false,
            cache: false,
            processData: false,
            success: function(data, status, xhr) {
                // ...
            },
            error: function(xhr, status, error) {
                // ...
            }
       });
    }));
});
1 upvote
  flag
thank you it is work on .xls upload files – Tarek Kalaji
upvote
  flag
What jQuery library do I need t o run this code? – Rayden Black
1 upvote
  flag
@RaydenBlack only jQuery. – Zayn Ali
upvote
  flag
how to get upload progress? – Ali Sherafat
upvote
  flag
@AliSherafat i've updated my answer. try it – Zayn Ali

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                          // 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.

3 upvote
  flag
One thing to note, based on the documentation: you should also send contentType: false. When I didn't send this with chrome the form content type was invalidated by jQuery. – ash
upvote
  flag
Nice answer. A few suggestions for improvement: Remove the parts of the code unrelated to the answer, for example the .done() and .fail() callbacks. Also, an example without the use of FormData and a list of pro/cons would be awesome. – Zero3
upvote
  flag
I got this error: TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement. – candlejack

Look for Handling the upload process for a file, asynchronously in here: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

Sample from the link

<?php
if (isset($_FILES['myFile'])) {
    // Example:
    move_uploaded_file($_FILES['myFile']['tmp_name'], "uploads/" . $_FILES['myFile']['name']);
    exit;
}
?><!DOCTYPE html>
<html>
<head>
    <title>dnd binary upload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript">
        function sendFile(file) {
            var uri = "/index.php";
            var xhr = new XMLHttpRequest();
            var fd = new FormData();

            xhr.open("POST", uri, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    // Handle response.
                    alert(xhr.responseText); // handle response.
                }
            };
            fd.append('myFile', file);
            // Initiate a multipart/form-data upload
            xhr.send(fd);
        }

        window.onload = function() {
            var dropzone = document.getElementById("dropzone");
            dropzone.ondragover = dropzone.ondragenter = function(event) {
                event.stopPropagation();
                event.preventDefault();
            }

            dropzone.ondrop = function(event) {
                event.stopPropagation();
                event.preventDefault();

                var filesArray = event.dataTransfer.files;
                for (var i=0; i<filesArray.length; i++) {
                    sendFile(filesArray[i]);
                }
            }
        }
    </script>
</head>
<body>
    <div>
        <div id="dropzone" style="margin:30px; width:500px; height:300px; border:1px dotted grey;">Drag & drop your file here...</div>
    </div>
</body>
</html>
var formData=new FormData();
formData.append("fieldname","value");
formData.append("image",$('[name="filename"]')[0].files[0]);

$.ajax({
    url:"page.php",
    data:formData,
    type: 'POST',
    dataType:"JSON",
    cache: false,
    contentType: false,
    processData: false,
    success:function(data){ }
});

You can use form data to post all your values including images.

5 upvote
  flag
Note: cache: false is redundant on a POST request as POST never caches. – Gone Coding
upvote
  flag
@Vivek Aasaithambi, I got this error: TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement. – candlejack

This is my solution for mvc using ajax.

<form enctype="multipart/form-data">    

    <div class="form-group">
        <label class="control-label col-md-2" for="apta_Description">Description</label>
        <div class="col-md-10">
            <input class="form-control text-box single-line" id="apta_Description" name="apta_Description" type="text" value="">
        </div>
    </div>

    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

and the js

<script>

    $(':button').click(function () {
        var formData = new FormData($('form')[0]);
        $.ajax({
            url: '@Url.Action("Save", "Home")',  
            type: 'POST',                
            success: completeHandler,
            data: formData,
            cache: false,
            contentType: false,
            processData: false
        });
    });    

    function completeHandler() {
        alert(":)");
    }    
</script>

Controller

[HttpPost]
public ActionResult Save(string apta_Description, HttpPostedFileBase file)
{
    return Json(":)");
}
1 upvote
  flag
You seem to have mixed some kind of framework into your answer. You should, at the very least, mention which framework your answer is usable for. Better yet, remove all the framework stuff and present only an answer to the question posed. – Zero3
1 upvote
  flag
so there's actually a mvc framework called "mvc"? and it uses csharpish syntax? that's cruel. – nonchip

Here's just another solution of how to upload file (without any plugin)

Using simple Javascripts and AJAX (with progress-bar)

HTML part

<form id="upload_form" enctype="multipart/form-data" method="post">
    <input type="file" name="file1" id="file1"><br>
    <input type="button" value="Upload File" onclick="uploadFile()">
    <progress id="progressBar" value="0" max="100" style="width:300px;"></progress>
    <h3 id="status"></h3>
    <p id="loaded_n_total"></p>
</form>

JS part

function _(el){
    return document.getElementById(el);
}
function uploadFile(){
    var file = _("file1").files[0];
    // alert(file.name+" | "+file.size+" | "+file.type);
    var formdata = new FormData();
    formdata.append("file1", file);
    var ajax = new XMLHttpRequest();
    ajax.upload.addEventListener("progress", progressHandler, false);
    ajax.addEventListener("load", completeHandler, false);
    ajax.addEventListener("error", errorHandler, false);
    ajax.addEventListener("abort", abortHandler, false);
    ajax.open("POST", "file_upload_parser.php");
    ajax.send(formdata);
}
function progressHandler(event){
    _("loaded_n_total").innerHTML = "Uploaded "+event.loaded+" bytes of "+event.total;
    var percent = (event.loaded / event.total) * 100;
    _("progressBar").value = Math.round(percent);
    _("status").innerHTML = Math.round(percent)+"% uploaded... please wait";
}
function completeHandler(event){
    _("status").innerHTML = event.target.responseText;
    _("progressBar").value = 0;
}
function errorHandler(event){
    _("status").innerHTML = "Upload Failed";
}
function abortHandler(event){
    _("status").innerHTML = "Upload Aborted";
}

PHP part

<?php
$fileName = $_FILES["file1"]["name"]; // The file name
$fileTmpLoc = $_FILES["file1"]["tmp_name"]; // File in the PHP tmp folder
$fileType = $_FILES["file1"]["type"]; // The type of file it is
$fileSize = $_FILES["file1"]["size"]; // File size in bytes
$fileErrorMsg = $_FILES["file1"]["error"]; // 0 for false... and 1 for true
if (!$fileTmpLoc) { // if file not chosen
    echo "ERROR: Please browse for a file before clicking the upload button.";
    exit();
}
if(move_uploaded_file($fileTmpLoc, "test_uploads/$fileName")){ // assuming the directory name 'test_uploads'
    echo "$fileName upload is complete";
} else {
    echo "move_uploaded_file function failed";
}
?>

Here's the EXAMPLE application

You can see a solved solution with a working demo here that allows you to preview and submit form files to the server. For your case, you need to use Ajax to facilitate the file upload to the server:

<from action="" id="formContent" method="post" enctype="multipart/form-data">
    <span>File</span>
    <input type="file" id="file" name="file" size="10"/>
    <input id="uploadbutton" type="button" value="Upload"/>
</form>

The data being submitted is a formdata. On your jQuery, use a form submit function instead of a button click to submit the form file as shown below.

$(document).ready(function () {
   $("#formContent").submit(function(e){

     e.preventDefault();
     var formdata = new FormData(this);

 $.ajax({
     url: "ajax_upload_image.php",
     type: "POST",
     data: formdata,
     mimeTypes:"multipart/form-data",
     contentType: false,
     cache: false,
     processData: false,
     success: function(){

     alert("successfully submitted");

     });
   });
});

View more details

Sample: If you use jQuery, you can do easy to an upload file. This is a small and strong jQuery plugin, http://jquery.malsup.com/form/.

Example

var $bar   = $('.ProgressBar');
$('.Form').ajaxForm({
  dataType: 'json',

  beforeSend: function(xhr) {
    var percentVal = '0%';
    $bar.width(percentVal);
  },

  uploadProgress: function(event, position, total, percentComplete) {
    var percentVal = percentComplete + '%';
    $bar.width(percentVal)
  },

  success: function(response) {
    // Response
  }
});

I hope it would be helpful

Not the answer you're looking for? Browse other questions tagged or ask your own question.