How to make sure download prompt is triggered using express sendFile? - node.js

I have the code below in my express server
app.get('/download', async (req, res)=> {
res.sendFile( `/dl/myfile.mp4`, {headers: {'Content-Type': 'mp4'},root: __dirname})
});
The sent file does not cause a download prompt in any of my tested browsers ( Chrome, Opera ) instead it shows me a player and starts playing the file while I need to it cause a download prompt.
How can I avoid the player and trigger a download prompt using Express?

You shoule use res.download(filePathToServer)
Transfers the file at path as an “attachment”. Typically, browsers will prompt the user for download if you use it.
You can read more about it here res.download - express

Related

How to serve word , excel , ppt and pdf files from node.js server

I have successfully upload file from mongoDB to my node.js server
Screen Short given below:
click here to see Screen Short
but I have no idea how to serve these files from node.js server to client side ..
Very Thankfull to advance
You can use something like this:
With this code, when you click a link to /pdf endpoint, the client will download a file with desired name.
app.get('/pdf', (req, res) => {
res.set('Content-disposition', 'attachment; filename=' + desiredName)
res.type(yourDataType)
res.status(200).send(Buffer.from(yourBufferFromFile, 'binary'))
})

Express JS download zip via endpoint

I'm trying to allow a user to be able to download a zip folder from a server via an express JS api call. I've created my folder with: zip -r download.zip folder-to-zip and am struggling to get it to download.
It seems if I make a GET request to some endpoint, it only downloads it to the server rather than the browser, my endpoint is:
router.get('/download', (req, res) => {
res.download('download.zip')
})
I need to attach something to a button that'll download this zip folder.
I haven't tested this, I'll update my answer when I have.
But I think doing something like:
router.get('/download', (req, res) => {
res.setHeader('Content-type','application/zip');
res.sendFile(__dirname + '/download.zip');
})
This is usually how I download files via express.

How to hide a download path of a file with Nodejs and Express

I have a situation where I want to hide the source path or download path of a file in my server from displaying on html. However, user is still be able to download it.
Any plugin for this? It's build with Nodejs and Express.
Perhaps you should create an API for it? Then you wont give away your file/folder structure.
router.get('/api/download-file', (req, res) => {
res.sendFile(your_file, {headers: {'Content-Type': 'your_file_type'}})
})

Express res.redirect shows content but not downloads

I have and API link what automatically starts downloading file if I follow it in address bar. Let's call it my-third-party-downloading-link-com.
But when in Express framework I set res.redirect(my-third-party-downloading-link-com). I get status code 301 and can see file content in Preview tab in developer tools. But I can't make Browser downloading this file.
My appropriate request handler is following:
downloadFeed(req, res) {
const { jobId, platform, fileName } = req.query;
const host = platform === 'production' ? configs.prodHost :
configs.stageHost;
const downloadLink = `${host}/api/v1/feedfile/${jobId}`;
// I also tried with these headers
// res.setHeader('Content-disposition', 'attachment;
// filename=${fileName}.gz');
// res.setHeader('Content-Type', 'application/x-gzip');
res.redirect(downloadLink)
}
P.S Now, to solve this problem, I build my-third-party-downloading-link-com on back-end, send it with res.end and then:
window.open(**my-third-party-downloading-link-com**, '_blank').
But I don't like this solution. How can I tell browser to start downloading content form this third-party API ?
According to the documentation, you should use res.download() to force a browser to prompt the user for download.
http://expressjs.com/es/api.html#res.download

Pass a file download from protected route to browser

I have a react frontend and a nodejs/express backend. The backend can serve files (downloads) via a protected route:
GET /api/file/:id
When the frontend wants to start a file download, it sends a request to this endpoint using this code (and the Authorization header is set with a valid token):
axios.get(`${apiURL}/file/${id}`)
.then(file => {
...
})
The backend responds with this code:
router.get('/file/:id', requireAuth, = (req, res, next) => {
...
res.set('Content-Type', 'application/pdf');
res.download(file.path, file.filename);
};);
This works fine: the download starts and the binary data is present in the file object of the .then() case of the axios call.
My question:
Instead of downloading the complete file I would like to pass the file to the browser BEFORE the file download starts, so that the browser handles the download like a usual browser-triggered-download, where the browser prompts wether it should download or display the file. How can this be done...?
The solution:
Thanks to #FakeRainBrigand tip I added token based authorization via request parameters to the route (using passport strategy):
const jwtOptions = {
jwtFromRequest: ExtractJwt.fromExtractors([
ExtractJwt.fromHeader('authorization'),
ExtractJwt.fromUrlQueryParameter('token'),
]),
secretOrKey: secretKey,
};
Now I can pass the download directly to the browser to handle it:
window.location.href = `${apiURL}/file/${_id}?token=${token}`;
The Authorization header is going to cause issues here. You should use cookies, at least for this feature. Otherwise, you'll have to include a token in the URL.
The two solutions are window.open in response to an event, or navigating to the url (e.g. location.href = '...').
At least in some browsers, they won't actually navigate when there's a file download, despite you changing the location.

Resources