Uploading Files Using XMLHttpRequest Level 2


As a part of HTML5, XMLHttpRequest API is undergoing enhancements. You can now upload files to a server and display a progress bar. Files are uploaded in their raw source format. That is not same as uploading a file using the old <input type="file"/> approach.

The basic steps are as follows:

  • Use the HTML5 File API to let the user select a list of files or drag and drop files on an element.
  • Upload these files using XMLHttpRequest Level 2.

Setting Up a Basic UI

Here is a very simple UI for dropping files and uploading them.

<div id="fileDrop">
       <p>Drop files here</p>
</div>
<a id="upload" href="#">Upload files</a>

You can style it better in real life. We will just show the basic code here.

Setting up File Drag and Drop

Within a <script> element, add these lines.

var files;

//Stop default actions
function stopProp(ev) {
    ev.stopPropagation();
    ev.preventDefault();
}

function init() {
    var dropZone = document.getElementById("fileDrop");
    //dropZone.addEventListener("dragenter",  stopProp, false);
    //dropZone.addEventListener("dragleave",  stopProp, false);
    dropZone.addEventListener("dragover",  stopProp, false);
    dropZone.addEventListener("drop",  setFile, false);
	
    var upload = document.getElementById("upload");
    upload.addEventListener("click",  doUpload, false);
}

//Save the dropped files
function setFile(e) {
    e.stopPropagation();
    e.preventDefault();

    files = e.dataTransfer.files;
	
    alert(files[0].name);

    return false;
}

window.onload = init;

function doUpload(e) {
  //Upload code here
}

Basically, when files are dropped, we save them in the files global variable. Also, we set the onclick handler of the Upload link to the doUpload() method.

Upload Files

To keep things simple in this article, we will upload only one of the dropped files. You can easily change the code to upload all files.

Fill out the doUpload() method as follows.

function doUpload(e) {
    var xhr = new XMLHttpRequest();
    var file = files[0];
    xhr.open("POST", "upload.jsp");
    //Set a few headers so we know the file name in the server
    xhr.setRequestHeader("Cache-Control", "no-cache");
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    xhr.setRequestHeader("X-File-Name", file.name);

    //Initiate upload
    xhr.send(file);

    stopProp(e);
}

The Server Side

The browser sends the contents of the file in the request body. A typical request will look like this.

POST /UploadTest/upload.jsp HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 48
Origin: http://localhost:8266
X-Requested-With: XMLHttpRequest
Cache-Control: no-cache
X-File-Name: Story.txt
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7
Accept: */*
Referer: http://localhost:8266/UploadTest/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: JSESSIONID=0CDE28BDE75AD2B9486070FDA5AED6DB

Long long ago....

In a galaxy far far away...

If the file is binary, all the bytes will be sent in raw form without any kind of base 64 encoding.

To read this type of data, you will need to get the input stream of the request. In a Servlet or JSP, this can be done by calling ServletInputStream getInputStream() method of HttpServletRequest object. Using the input stream, you can read all the data.

  1. #1 by Ricardo on July 29, 2013 - 3:20 pm

    Very nice!

(will not be published)

*