18

I try to send file to client with this code:

router.get('/get/myfile', function (req, res, next) {
  res.sendFile("/other_file_name.dat");
});

it's work fine but I need that when user download this file from the url:

http://mynodejssite.com/get/myfile

the filename into the browser must be "other_file_name.dat" and not "myfile".

Jacob Ford
  • 4,553
  • 5
  • 27
  • 42
Massimo Caroccia
  • 417
  • 2
  • 6
  • 14

4 Answers4

33

there is a specialized method res.download

which covers all for you ;)

router.get('/get/myfile', function (req, res) {
    res.download("/file_in_filesystem.dat", "name_in_browsers_downloads.dat");
});
Michal Miky Jankovský
  • 3,089
  • 1
  • 35
  • 36
12

This is my solution:

var fs = require('fs');
var path = require('path');
const transfer = exports;

transfer.responseFile = function (basePath, fileName, res) {
    var fullFileName = path.join(basePath, fileName);

    fs.exists(fullFileName, function (exist) {
        if (exist) {
            var filename = path.basename(fullFileName);

            res.setHeader('Content-Disposition', 'attachment; filename=' + filename);
            res.setHeader('Content-Transfer-Encoding', 'binary');
            res.setHeader('Content-Type', 'application/octet-stream');

            res.sendFile(fullFileName)
        } else {
            res.sendStatus(404);
        }
    });
};

and use it:

router.get('/myfile', function (req, res) {
    transfer.responseFile("/var/nodejs", 'fileToDownload.dat', res);
});

Thank you to all helpers :)

Massimo Caroccia
  • 417
  • 2
  • 6
  • 14
2

If you have multiple routes like below: "/get/myfile1", "/get/myfile2", "/get/myfile

Why don't you make a generic one. which can handle all request and it will solve your link(download_name) problem too. You can do it as below

router.get('/get/:fileName',function(req,res){
    res.sendFile('/file_path/'+req.params.fileName)
});

Edit After Comment (EDIT 1):

Sorry, i didn't get your point. I am assuming that if you are developing the backend api, you should have the control of choosing the url too, right ?

Giving an example:

when server side is this:

router.get('/get/:fileName',function(req,res){
    res.sendFile('/file_path/'+req.params.fileName)
});

Based on your posted code and implementation. The files which need to get downloaded are finite in number and known files.

assuming there are 2 files : "file1.dat" and "file2.dat"

you can call the api as below right ?

  1. http://yourapi.com/get/file1.dat
  2. http://yourapi.com/get/file2.dat

am i missing something ?

EDIT 2:

If that is the case, i think this would solve your problem, instead of using sendFile use res.attachment:

app.get('/get/myfile',function(req,res){
        res.attachment('/file.txt');
        res.end('Downloaded', 'UTF-8')
});
  • This is a good solution but the problem is that the original filename is different by the url. – Massimo Caroccia Jan 30 '17 at 18:01
  • Sorry, i didn't get your point. I am assuming that if you are developing the backend api, you should have the control of choosing the url too, right ? Giving an expample: when server side is this: router.get('/get/:fileName',function(req,res){ res.sendFile('/file_path/'+req.params.fileName) }); Based on your posted code and implementation. The files which need to get downloaded are finite in number and known files. assuming there are 2 files : "file1.dat" and "file2.dat" you can call the api as below right ? 1. yourapi.com/get/file1.dat 2. yourapi.com/get/file2.dat – Pankaj kumar Panigrahi Jan 30 '17 at 18:06
  • No, the url need to be without the filename and without extension. – Massimo Caroccia Jan 30 '17 at 18:11
  • Let me know if Edit 2 fixed your issue – Pankaj kumar Panigrahi Jan 30 '17 at 18:28
  • app.get('/get/myfile',function(req,res){ res.attachment('/file.txt'); res.send('/file.txt'); }); – Massimo Caroccia Jan 31 '17 at 08:16
0

This worked for me in case is useful for someone

res.sendFile('filepath', { headers: { 'filename': 'myfile' } }, (error) => errorHandlerFunc() )

sgClaudia98
  • 236
  • 4
  • 14