Search code examples
javascriptinternet-explorercross-browseractivexobject

Reliable Javascript way to do feature/object detection for SaveAs dialog in IE


I'm looking for a cross-browser solution to display a "Save As" dialog in Javascript. I had been using this method in a previous project, but it's broken in IE 11 (because the window.ActiveXObject has changed and IE 11 now slips into the first conditional below):

function saveFile(fileURL, fileName) {
    if (!window.ActiveXObject) {
        // Non-IE
        var save = document.createElement('a');
        save.href = fileURL;
        save.target = '_blank';
        save.download = fileName || fileURL;
        var evt = document.createEvent('MouseEvents');
        evt.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0,
            false, false, false, false, 0, null);
        save.dispatchEvent(evt);
        (window.URL || window.webkitURL).revokeObjectURL(save.href);
    } else if (document.execCommand) {
        // IE
        var _window = window.open(fileURL, "_blank");
        _window.document.close();
        _window.document.execCommand('SaveAs', true, fileName || fileURL)
        _window.close();
    }
}

My understanding is that the IE team did this intentionally to prevent using this method for browser detection. Can I use some other kind of feature/object detection to make it work again. Or can I (preferably) remove the conditionals and just have one piece of code for all browsers. When the first conditional runs in IE, the error I see is:

DOM7001: Invalid argument 'url'. Failed to revoke Blob URL: '[the url...]'.
File: localhost:8080

I know that browser detection is an option (like WhichBrowser, for example) but even the author of that warns that feature/object detection really is the way to go.


Solution

  • I think it's probably a better solution to just embed a hidden iFrame in the HTML body and have the JS set the src of the iFrame to the URL. Once the src is set, that'll immediately trigger the Save-As dialog if the src URL wants it to e.g.

    <body>
    ...
    ...
    <iframe style="display:none" id="hidden-iframe"></iframe>
    </body>
    

    and...

    document.getElementById("hidden-iframe").src = myURL;
    

    Seems to be working in all the browsers I've checked so far, including IE (gasp!).