Github Twitter 2 Delicious Linkedin Stackoverflow Google plus new 32px Rss

File Uploading over AJAX using HTML5

Using the HTML5 File API to upload files over AJAX is a great way to to add file upload capabilities and not resort to using a flash based solution or iframe hacks.

It's easy to use and works with most modern browsers. This example use the Data URI Scheme to transfer the file over AJAX.

The mime type and base64 encoded file are sent as a standard parameter on a POST request. The server then decodes the image and saves it.

Data URI Scheme

An image can be embedded in a HTML or CSS document using this method. The example below is an encoded red dot image. The browser is just reading the embedded image as it's src attribute (scroll to see the entire URI).


Client Side

On the client side your going to need to bind a change event to the file attachment field. The change event loops over all the files chosen, creates a FileReader object which uses the readAsDataURL method to encode the file using the Data URI Scheme. An object containing the orignial filename and data is then added to an array.

When the form is submitted each file in the array is read and sent across in an AJAX call.

Client side javascript
    var files = [];

    $("input[type=file]").change(function(event) {
      $.each(, function(index, file) {
        var reader = new FileReader();
        reader.onload = function(event) {  
          object = {};
          object.filename =;

    $("form").submit(function(form) {
      $.each(files, function(index, file) {
        $.ajax({url: "/ajax-upload",
              type: 'POST',
              data: {filename: file.filename, data:},
              success: function(data, status, xhr) {}
      files = [];

Server Side

The AJAX endpoint on the server just has to read the data and reassemble the file. Since we only want the actual file data we need to cut away the mime type and encoding. So we just look for base64, and take everything after it.

Sinatra endpoint
    post "/ajax-upload" do
      data = params[:data]
      filename = params[:filename]

      ## Decode the image
      data_index = data.index('base64') + 7
      filedata = data.slice(data_index, data.length)
      decoded_image = Base64.decode64(filedata)
      ## Write the file to the system
      file ="public/uploads/#{filename}", "w+")


Example Application

If you wanna just checkout a complete working example head on over to Github, clone the repo and run:
$ bundle install && bundle exec thin start

Related Links


Joe says:
07/27/2012 11:33am

The demo seems cant run on my machine. eventmachine gem got errors when I try to install it.

BTW, is there any tutorial that about upload multi-file at once by using carrierwave + some java uploader?

Nick DeSteffen
07/29/2012 04:37pm

I'm not sure what error you are having. The demo uses Thin for a server, you might be missing some libraries. If you post the error I might be able to help you out, but without it I really don't know.


meagar says:
05/28/2013 04:52pm

Note that this will open as many simultaneous connections as you select files, or as your browser supports. You should probably not be using $.each here, as the body of each iteration is asynchronous.

Nick DeSteffen
05/31/2013 04:52pm

@meagar -- correct, you would probably want to limit it to 1 file or put in some client side validations to ensure that only a few files could be uploaded at a time.

Oscar says:
10/22/2013 11:21pm

Hi guys!

About prevent using $, I would like to know what do you think about sending the file content as a string with delimiter...


papucho says:
03/24/2014 07:36pm

Thank a lot. This saved me a lot of time!

Vadim says:
07/18/2014 02:10pm

thanks a lot for great post!

suresh atta
12/19/2014 06:48am

Good one ...

koundinya b
koundinya b says:
03/03/2015 02:57am

Hi, Is there any limit to file size and if there is how to change it.

Dani says:
03/17/2016 08:48am

Thanks!! Works for me.

GeraldSef says:
08/26/2017 01:39am

VMN is great for companies simply because customers don't have to pay premium costs to deliver messages. They are charged standard tariff rates for sending SMS to VMN. Such a quantity enables users to send SMS to your application centre which is right on your desktop.

Fax Tones Cause Discomfort- In the year 2007 you ought to no longer have a fax machine that shares your telephone line. If you have to say, "Okay give me a few minutes to turn my fax device on prior to you send the fax," and then give anybody else that calls throughout that time a piercing scream to the ear, it is time to improve. There are web fax options as nicely as get virtual sms number that allow you to still have the one number for phone and fax, but will also permit each sorts of phone calls to arrive in at the exact same time with out getting to flip any switches.

Low-price 800 Numbers: Want to make it totally free for a great deal of callers without bankrupting you? Most VoIP providers offer cheap 800 figures - totally free to the caller, fixed month-to-month rate for you (varies, but approximately $5 for the initial one hundred minutes every thirty day period, then four.5-cents or so per minute past that).

Cloud PBX phone method is a new era phone system. Cloud refers to "internet" and PBX is "Private Department Trade". The method is features utilizing the web and trunk lines thus it is in a position to decrease telecommunication price by much more than 70%25.

You can use telephone and multi-media conferencing to reduce down on travel. Free telephone conferencing is accessible from companies this kind of as FreeConference. If you require multi-media, such as phone and pc sharing, use WebEx, Microsoft LiveMeeting, GoToMeeting, or Look.Internet.

You will save tons of cash. Why pay $40 to $60 a thirty day period with a conventional phone services when you can pay much less than $10 per month with a quality VOIP supplier when you buy 1 year up front and get the 2nd year totally free? Conserve hundreds of bucks every year and speak till your heart is content.

Format using Markdown