Question in brief
From within a JavaScript web application how can I have a user's browser download a large (on the order of gigabytes), dynamically generated file from a RESTful endpoint which requires the setting of headers?
Question at length
From within a JavaScript web application I need to provide users with the ability to download a potentially large (~GBs), dynamically generated file in one of several formats (eg text/flatfile
, application/vnd.ms-excel
, and others) from a RESTful API. The desired format is indicated in the header of the request. For example, to download a fasta format version of the file:
curl -s -H 'accept:text/fasta' 'https://.../api/download?query=human'
The back end will run the query, retrieve the results, and return a file in the fasta format. An issue arises when I want the front end application to provide a download link to the user. Disregarding the need for setting headers I can create a download link like so:
const link = document.createElement('a');
link.href = "https://.../api/download?query=human";
link.setAttribute('download', 'download');
document.body.appendChild(link);
link.click();
or equivalently as HTML:
<a download href="https://.../api/download?query=human">
download human fasta
</a>
However, as far as I know, I don't have a means of setting the header to specify the format. I could make a request within the app itself:
axios.get(
'https://.../api/download?query=human',
{
headers: {
Accept: 'text/fasta',
},
}
)
.then(response => {
// provide response.data to the client as a download link
});
However, I can see several problems with this:
- This will fill up the user's browser's memory (and these can be large downloads)
- There will be no indication of progress (eg 50% done)
- It will be tied to the web app's browser tab as it's not a separate download process. If this is closed the download cancels.
Potential front end solution
Problems 1 and 2 could potentially be solved with the Streams API but problem 3 would still exist.
Potential back end solution
As the back end team who manage the API are open to modifications a potential (and less RESTful way) solution is to request a particular file format is by using a format
parameter in the url. Then to access the fasta format of the "human" query I can do:
<a download href="https://.../api/download?query=human&format=flatfile">
download human fasta
</a>
Do other solutions or approaches exist?