github twitter linkedin email
Uploading to Azure Blob Storage in AngularJS With a HTML5 Web Worker
Mar 31, 2015
3 minutes read

View on Github | Just the Web Worker

This was a recent problem I solved at UMG. We were eager to replace an aging Silverlight component that handled uploading files into Azure Blob Storage via parallel blocks with MD5 calculation for integrity. We had to be sure we got at least very similar speeds and didn’t degrade the user’s experience while the upload was in progress.

I’d first created an Angular factory that handled the whole process of slicing up the file into blocks, calculating the MD5 of those blocks and uploading them. It also calculated the MD5 of the whole file as we would use that later on (Azure can store this but won’t perform any checks).

The problem with running all of that in the main browser thread was the MD5 calculations degraded the browsing experience to almost standstill. We wanted the users to be able to continue what they were doing as these files could be quite large. My immediate attention was turned to something called Web Workers which was perfect for this type of background task.

Notes On Web Workers

Getting Things Working In Your Web Worker

A web worker is basically a separate thread, and usually one single javascript file. An example initialisation of a web worker:

var worker = new window.Worker('mySuperWorker.js');

That’s it. But you’ll need to communicate with your worker, right? Here’s a better example.

A simple async maths worker, asyncMaths.js

(function() {

    function add(a, b) {
        self.postMessage({ type: 'result', result: (a + b) });
    }

    self.onmessage = function(e) {
        switch(e.data.type) {
            case 'add':
                add(e.data.a, e.data.b);
                break;
        }
    };
})();

Call from our browser

var worker = new window.Worker('asyncMaths.js');

worker.onmessage = function(e) {
    switch(e.data.type) {
        case 'result':
            console.log('Result ' + e.data.result);
            break;
    }
};

worker.postMessage({ type: 'add', a: 11, b: 19 });

Getting External Libraries Into Your Web Worker

Another issue you’ll face is getting your external libraries (think underscore.js) to work in your web worker. The file is loaded in isoliation so you’ll have to call the following:

(function() {

    self.onmessage = function(e) {
        importScripts('/scripts/underscore-min.js');
    };
})();

Using The Library In AngularJS

Require the azureBlobStorage module:

angular.module('appx', ['azureBlobStorage']);

Use the service in your controller, make sure the paths are correct!

angular.module('appx').controller('UploadController', [
    '$scope', 'azureBlobUpload',
    function($scope, azureBlobUpload) {
        // Get your blobUri from your server

        var fromServer = 'xxx';

        $scope.upload = function(files) {
            azureBlobUpload.upload({
                path: '/scripts/azure-blob-upload/dist/',
                libPath: '/scripts/azure-blob-upload/libs/',
                blobUri: fromServer,
                file: files[0],
                progess: function (result) {
                    // result.progress is the percentage of progress
                },
                complete: function (result) {
                    // result.md5 if calculateFileMd5 is set
                },
                error: function (data, status) {
                },
                blockSize: 1024, // optional
                calculateFileMd5: false // optional, false by default
            });
        };
    }
]);

Using The Web Worker Externally

You could also use the Web Worker outside of Angular. Take a look at the app/azureBlobUpload.js file and do something similar in your application.


Back to posts


comments powered by Disqus