Search code examples
asp.netangulartypescriptblobfilesaver.js

cross-browser solution for downloading large files from authenticated endpoint


I'm searching for a way for downloading big files (like 2 - 4 Gb) on a bearer token protected api endpoint, that works on all common browsers (IE 11, Chrome, Firefox, Android Browsers, Safari). It should work with angular/ts and browsers only (without providing an app).

The problem with FileSaver

At the moment I'm using eligrey/filesaver which kinda combines all browser specific possibilities for a client side blob download. With this approach i can easely use the bearer token (ex. with http interceptors).

The problem is, IE pumps up the RAM and gets stuck at 1.4 GB download.

The problem with StreamSaver

I saw there is a new modern way with StreamSaver.js, which allows streaming directly on disk, but it is only available on chrome and opera.

The Problem with an unprotected endpoint

Another common way for such a scenario would be to allow anonymous access for the download endpoint, with requesting a one-time-token first, creating a url containing this token, let the user download it directly via browser with opening a new tab and immediately close it after starting the download.

This approach takes 2 requests for a download and looks flashy for a user to watch. I'm not sure, if this works on mobile browsers (opening new tab for download) and it looks like a hack, at least to me. The API have to ensure that url's are only valid during a short period of time and/or cannot be used 2 times in a row.

Ideas, anyone?

Does anyone knows a clean, modern/state of the art & performant way for such a common scenario?

How are the big companys dealing with this problem (google drive, dropbox, amazaon)?

I personally would prefer to let the browser download the file (instead of client side blob download). Maybe there is a way to "inject" the bearer tokens as default request headers to the browser when the client clicks a (href'ed) link.

Why isn't it easy for an modern angular rich-client to delegate a protected binary download to the browser?


Solution

  • Unfortunately I'm not aware of any method to solve your issue regarding FileSaver.js and StreamSaver.js.

    Nonetheless I had a similiar problem to solve, which points at your thoughts of using an "unprotected endpoint".

    Well, I would go and create a one-time token to the file, which is included in URL of course. (I know, I know, it's not the best solution - I'd appreciate if someone comes up with a "best" practice for this)

    Your thoughts mentioned a "flashy" and nasty behaviour for the user. I found a solution to solve this "flashy" problem by injecting a form which triggers the download.

    jQuery('<form action="' + YOUR_URL + '" method="get"></form>')
        .appendTo('body')
        .submit()
        .remove();
    

    The download is then handled by the standard download dialog of your browser, without that nasty a new tab opens and closes immediately.

    Note:

    I haven't tested this for files of your size. But it works for files until 1GB flawlessly. Maybe you give it a shot and I hope this helps.