A brief overview on the whys and hows of using HTML’s XHR2 API for file transfer. In addition to the overview, jQuery-based sample JavaScript is provided for the client side. Skip to sample code ⇒

XHR2: Yup, it’s TCP. FileCatalyst specializes in fast UDP. Why use it?

Although FileCatalyst technology is based primarily on UDP, there are times that TCP is still needed. For example, although some corporate environments might block or otherwise restrict UDP, those same organizations almost always have HTTP (itself built on TCP) in and out for internet usage.

FileCatalyst HTTP Tunnelling technology (available standalone, in FileCatalyst Webmail and Workflow, or as an add-on for FileCatalyst Direct) takes advantage of this opportunity by accepting uploads through HTTP POST/PUT, and then moving the files through the internal network using the best available protocol.

How to implement simple XHR2 on the client side

What we’re replacing: When our legacy form uploader was created, the method of choice was simply submitting a form containing one or more file inputs and encoding as mulipart/form-data:

select file:

All required components fairly handily enabled and working through nothing more than HTML. However, there are two significant problems: 1) the POST is a blocking call, meaning you need to jump through hoops in order to keep the UI updated and interactive. 2) You do not have client-side access to rich information about the upload; and even if you did, refer back to point #1 to see why it wouldn’t matter much.

The new way (XHR2): with a little bit of JavaScript, you solve the problem of the blocked UI, and also have access to far more information about each individual file transfer, including client-side progress.

To create a form capable of accepting multiple files and using XHR2, we need to update our form’s input: add the “multiple” property, remove the form action, switch the encoding type to “octet-stream”, and give the form an ID for easy selection in JavaScript. Let’s also create an empty element into which we will push some progress information later.

select file(s):

When one or more files are selected and you have a capable browser, an object called a fileList is attached to the input. This object can be used for the same kind of form submit used in the legacy example, but it also includes everything you need to invoke the xhr2 API. Let’s set up a listener for the input’s change event. On change, we will capture the fileList and store a pointer to it. Note that it is assumed #uploadForm is available for scripting (this method might be in your document ready function for example).

var up = up || {} /* let's namespace everything under an object called "up" */

$('#uploadForm').on('change', '#files', function(evt) {
  up.fileList =;

Now that we have access to the fileList, we can iterate through it at will, and instead of submitting all files together as a multipart POST, we can separate them and send them out. Let’s make sure we have a listener for starting the whole thing off:

$("#uploadForm").on("click", function(e) {

All the above does is invoke an iterator, which in itself only serves to divide the fileList up into individual files for creating individual XHR objects:

up.processFiles = function(fileList) {
  for (var i = 0, len = fileList.length; i < len; i++) {
    file = fileList[i];
    up.uploadFile(file, i); // send each one individually

As mentioned, all the above does is send files one at a time into an upload function. The uploadFile function will create an array of XHR objects, each containing everything you need to track progress, names, etc. It will also do some cosmetic work, creating an array of progress nodes in the DOM. As each XHR object is created, the stream is opened and the file is sent along it.

up.uploadFile = function(file, index) {

// create the empty XHR objects and some nodes, cached by index.
  up.xhr = [];
  up.xhr[index] = new XMLHttpRequest();
  up.progressNode = [];
  up.progressNode[index] = $('

Progress for ' + + ': '); up.progressNode[index].appendTo('#progressContainer'); // of the various pieces of data available, let's just use the "loaded" (in bytes) // and the "total" (in bytes) to generate a percentage of progress. XHR2 has a // "progress" event that will serve as the trigger. up.xhr[index].addEventListener("progress", function(evt) { if (evt.lengthComputable) { var sofar = Math.floor((evt.loaded / * 10000) / 100; up.progressNode[index].append(' ' + sofar + '%'); } }, false); // The upload itself. The funcion opens the stream, then some // headers are set, and finally, "send" is invoked with the file that was // passed into this function var remoteURL = ""; // where the URL is able to receive incoming octet-stream data via POST. up.xhr[index].open("post", remoteURL, true); up.xhr[index].setRequestHeader("Content-Type", "application/octet-stream"); up.xhr[index].setRequestHeader("X-File-Name",; up.xhr[index].setRequestHeader("X-File-Type", file.type); up.xhr[index].send(file); };

Wrap Up

It might seem like a lot of code, but a lot of that is just plumbing. The meat of it is simply this:

  • The file input element allows the user to select files, at which time a fileList object is created. This object is already XHR2 in compatible browsers.
  • If we iterate through the whole fileList, we can create an XHR object PER file, so that we can track on a per-file basis
  • As we iterate through the fileList and create objects, we can automatically open the stream for each, set the headers for each, and invoke xhr.send(file) to kick it all off

In future installments, we will talk about what's required on the server side to receive this transfer. Since our application also has a "web server to file server" leg, we also have a polling mechanism for reporting progress of that leg (a server-side leg, vs. the client-side leg of this article).