When we first started working on MindMup, the only cross-browser compatible way of saving images to a document locally on the client was to paint them on a canvas, and then export the canvas to a data URI. This involves creating invisible DOM elements and actually recoding images into PNG, so it always felt a bit sub-optimal. Plus it only works for images, and other type of resources couldn’t be cached like that.

Cross-browser support for HTML5 APIs significantly improved over the last few years, so it turns out this is now possible without resampling/recoding images or using invisible DOM elements, in a generic way that can work with any content type, with just a few lines of code.

var downloadAsDataUri = function (url) {
  return new Promise(function (resolve, reject) {
    var fileReader = new FileReader(),
        xhr = new XMLHttpRequest(),
        onXHRdone = function () {
          var b = new Blob([xhr.response], 
            {type: xhr.getResponseHeader('content-type')});
          fileReader.readAsDataURL(b);
        };
    fileReader.onload = function () {
      resolve(fileReader.result);
    };
    fileReader.onerror = reject;
    xhr.responseType = 'arraybuffer';
    xhr.open('GET', url, true);
    xhr.onload = onXHRdone;
    xhr.onerror = reject;
    xhr.send();
  });
};

Try it out