Download large file with authorization headers

Viewed 122

In my React app, I want to have a button to download a file that behaves identical to a <a href="..." download /> link:

  • When clicking on it, the user gets asked immediately whether to download or open the file (before the download starts)
  • The download progress is shown in the browser download list
  • The download can be streamed to disk immediately, without filling up the browser memory so it works for large files as well
  • I need to pass in a Bearer token in the header (which is the reason I cannot use the <a href download/> approach)

The solution I find online is using

fetch(... including the bearer token in the header)
.then(res => res.blob() )
.then(data => {
  const link = document.createElement("a");
  link.href = window.URL.createObjectURL(new Blob([data], { type: "application/octet-stream" }));
  link.download = fileName;
  document.body.append(link);
  link.click();
  window.URL.revokeObjectURL(link.href);
});

but this has 2 obvious drawbacks:

  • The user only gets to see the "download or open" dialog after the file has downloaded. For large files where the download takes a while, it simply looks like nothing is happening after clicking
  • For downloads that don't fit into the memory of the browser, it crashes.

I also saw the downloads.download() API but that doesn't work in Safari yet so I didn't try it as I need to support all major browsers.

The last option (that I didn't explore in detail) is using the fetch().then(res => res.body) and do something with the stream. It would allow me to stream the download directly to a file, but I fail to see how I would ever show the "download or open" dialog to the user, and how to get access to the file location the user chooses for the download.

Having a button to download a (large) file in a React app doesn't sound like a far fetched requirement, so I'm probably overlooking something trivial. Can somebody point me in the right direction ?

0 Answers
Related