#How to send frontend a file that I keep as a S3 link in my backend?

23 messages ยท Page 1 of 1 (latest)

hexed dew
#

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?

past rune
#

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

hexed dew
#

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.

past rune
#

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

hexed dew
#

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

past rune
#

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)

hexed dew
#

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?

past rune
#

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

hexed dew
#

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..

hexed dew
past rune
#

Does the Content-Type come in correctly and do you see the expected headers?

hexed dew
#

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.

past rune
#

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

hexed dew
#

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 ๐Ÿ˜„

haughty canyon
hexed dew
haughty canyon
hexed dew
#

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