Advanced Uploading Techniques — Part 2


In our previous tutorial on chunked uploading, we learned how to build an uploading system using the File API to send small chunks of data to better respond to the bandwidth demands of mobile upload speeds and large files. We also learned how this opened up the ability for us to pause and resume uploads with the push of a button. Our goal is to build an uploader capable of correcting errors during the upload process automatically. The first of these which we will address is the lack of a connection. Hardwired ethernet connections will always provide the most stable uploads, but for mobile browsers, especially ones not connected via WiFi, we must be able to react to a loss of connection.

Introducing the online and offline events

Happily, this is ridiculously easy in modern browsers, and since the browsers which support our chunked upload also support these events, we don’t have to commit to writing a lot of code. The constructor to our updated ChunkedUploader class now looks like this:

function ChunkedUploader(file, options) {
    if (!this instanceof ChunkedUploader) {
        return new ChunkedUploader(file, options);
    }
 
    this.file = file;
 
    this.options = $.extend({
        url: '/upload'
    }, options);
 
    this.file_size = this.file.size;
    this.chunk_size = (1024 * 100); // 100KB
    this.range_start = 0;
    this.range_end = this.chunk_size;
 
    if ('mozSlice' in this.file) {
        this.slice_method = 'mozSlice';
    }
    else if ('webkitSlice' in this.file) {
        this.slice_method = 'webkitSlice';
    }
    else {
        this.slice_method = 'slice';
    }
 
    this.upload_request = new XMLHttpRequest();
    this.upload_request.onload = this._onChunkComplete;
 
    // Respond to changes in connection
    if ('onLine' in navigator) {
        window.addEventListener('online', this._onConnectionFound);
        window.addEventListener('offline', this._onConnectionLost);
    }
}

The implementation of those events (which you should place on the prototype of ChunkedUploader), is also quite straightforward:

ChunkedUploader.prototype = {
 
// Internal Methods __________________________________________________
 
    // ...existing prototype code
 
// Event Handlers ____________________________________________________
 
    // ...existing prototype code
 
    function _onConnectionFound() {
        this.resume();
    }
 
    function _onConnectionLost() {
        this.pause();
    }
}

And that’s it! As a bit of homework/extra credit, you’ll want your ChunkedUploader class to dispatch events when it is paused so the view can properly react to these changes in connection. Rework the controller code from the previous tutorial to change the state of the pause/resume button based on pause and resume events dispatched from the class, rather than the actual click event of the button.

More Reading: