4

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?

Benjamin Schäublin
  • 1,526
  • 1
  • 16
  • 26
  • One approach I've seen in the past is to generate a short-lived unauthenticated URL to download the file. S3 access links that expire automatically are one way to achieve this, assuming your files are on S3. – Nate Barbettini Jan 16 '18 at 16:33

2 Answers2

2

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.

r3dst0rm
  • 1,876
  • 15
  • 21
  • thank you for sharing your experience with this! Can you say anything about this approach on mobile devices (android browser, iOS safari?). I'll definitly try that - if i really have to go that way (well.. it looks like, there is no other option ;o)). At least there is no "flashy" effect that way. – Benjamin Schäublin Jan 23 '18 at 08:30
  • 1
    It's working on Chrome for Android and Stock Android Browsers like Samsungs (don't know how they call it). I even created an app which consists of a webview for Android - works, no problems there. Also it's working iOS running Safari. But still, if you should encounter a problem there, let me know. – r3dst0rm Jan 23 '18 at 08:39
  • 1
    cool, thanks - if no one brings up a better solution in 5 hours, i'll accept yours – Benjamin Schäublin Jan 23 '18 at 08:46
1

Why not websocket ? Expecting that it is probably not the best method (according to the best answer of this near similar question), but I copy-paste the @Ibrahim Muhammad's answer in case it may help you:

You could use https://github.com/binaryjs/binaryjs or https://github.com/liamks/Delivery.js if you can run node.js on the server.

A. STEFANI
  • 6,707
  • 1
  • 23
  • 48
  • Thank you, i'll take a look at it. But as i know websockets are not doing great with internet explorer..? Unfortunately I can't run nodejs there. – Benjamin Schäublin Jan 22 '18 at 06:58