Pages

Monday, August 18, 2014

Angular.JS Service to Download Data Generated in Browser

I ran into a situation where I wanted to be able to download data that was generated in the browser. There are several libraries that handle this scenario, but I thought it should have been simpler than those large libraries.

Below is the result. It supports IE 10+ (potentially 9 haven't tested), FireFox, and Chrome.
angular.module('FileDownload')
.service('SaveFileService', [function () {
        this.Save = function(data, filename, mimeType) {
            var blob = new Blob([data.join('\n')], {type: mimeType});
            if (/\bMSIE\b|\bTrident\b|\bEdge\b/.test(navigator.userAgent)) {
                window.navigator.msSaveOrOpenBlob(blob, filename);
            } else {
                var url  = window.URL || window.webkitURL,
                    link = document.createElementNS("http://www.w3.org/1999/xhtml", "a"),
                    event = document.createEvent("MouseEvents");
                
                link.href = url.createObjectURL(blob);
                link.download = filename;

                event.initEvent("click", true, false);
                link.dispatchEvent(event);
            }
        };
    }]);
Basically, the Save function does a couple things. For IE browsers, it creates the blob and calls the msSaveOrOpenBlob (the msSaveBlob function would make IE only display a save dialog and not give the user the option to open it). For all other browsers, it creates the blob, generates a link element, creates a mouse click event, and has the link dispatch the created event.

To use the service, just inject the service into the controller and call the Save function w/ the needed parameters.

UPDATE 2015-09-28: Per Kevin's feedback, I have updated the regular expression to catch the Edge browser (so much for Microsoft making a standards evergreen browser). I have verified that the above change works as advertised.

2 comments:

  1. I'm using this in my project, tested it for IE10, IE11, Firefox, Chrome and Opera. It doesn't work anymore for Edge but you just need to change the regex to /\bMSIE\b|\bTrident\b|\bEdge\b/

    ReplyDelete
  2. Kevin: I successfully tested your change in my demo application and updated my example accordingly. Thanks for the feedback!

    ReplyDelete