Heyo fellow NestJS devs.
I got an FileEntity which has an s3_link attribute. A user clicks on a download button and hits file/download/:fileId and wants to download that file which actually lies on S3 and not directly on my server. How can I make NestJS send it that file as a download? Does that even work? Is that the right approach?
#How to send frontend a file that I keep as a S3 link in my backend?
23 messages ยท Page 1 of 1 (latest)
You're wanting to make the browser download the file via the Nest server, right? Not have the Nest server return the URL for the browser to then fetch from
Yes exactly, the former. I already thought about just passing the file link to an a href tag with the download attribute, but StackOverflow said that way isnt failproof.
So you can use S3 to get the file back, if possible get it as a stream or a Buffer, and then return a StreamableFile instance with the stream/buffer passed to the constructor and the proper content disposition set as part of the second parameter for the StreamableFile's constructor
Ahh already thought it would be possible that way, but it seems so overengineered. Damn thought there would be somehow an easier solution ๐ something like res.send(new StreamableFile(s3Link)) ๐
naive again
Returning a StreamableFile ends up calling stream.pipe(res) under the hood for you. You still need to get the stream from the source though (S3 in this case)
Okay @past rune some hours later I got it almooost figured out:
I send back the StreamableFIle and set all the important things, however the browser does not initiate a save file dialog of some sort, but just gets back that blob (I guess) "Antwort"/answer on the right. Any idea of an easy to forget culprit?
return new StreamableFile(file.Body, { disposition: 'attachment; filename="file.mp3"', type: 'audio/mp3' }) I believe should do it. Might need to double check some of the options in that second parameter
Ahh my stuff with res.XYZ() does the same actually. However I guess it doesnt work because I do an POST request, could that be? All the example I see do a GET. Maybe for a POST the browser does not invoke the file save dialog ๐
I am just wondering because your suggestion also didnt work, but I guess both ways are correct..
Ok nope, wrong assumption. Refactored everything to GET, still no download invoked. Weeeird, something small is missing ๐
Does the Content-Type come in correctly and do you see the expected headers?
Yes, check that one out
Ah lol sorry, I guess the backend part is all correct. The frontend just doesnt magically spin up a file save dialogue.
Thats what I currently do and of course it just takes the data and does nothing with it ๐ damn developing for so long now, but never did a proper file download integration from backend to frontend.
Try setting axios's { responseType: 'blob' }. I think that would do it. That, or possibly a simple XMLHttpRequest
Or just a link to that endpoint and let the browser handle it from there
Its funny, I thought that would be super native, but I need to npm i something like js-file-download and then FileSaver.saveAs(res.data, "name.mp3") for it to work ๐ would never have thought that
This also works lol, what an ugly way of doing things ๐
You can also just set window.location.href to the file link and the save dialog will pop up automatically
You mean not involving the backend at all?
Skipped that solution because of that SO answer:
https://stackoverflow.com/a/50695407/10144565
No, I mean, you set window.location.href to the url of your backend. Instead of creating a link element and programatically clicking on it.
Ahh just got you and tried that out, however that opens the file in preview mode and plays it directly in the browser somehow. No file dialogue or immediate download