File download from server in NodeJS

11,878

res.download() doesn't take in data. It takes a file path.

http://expressjs.com/en/api.html#res.download

You want to call res.download within a successful fs.writeFile callback

var fileName = "presentation.pcap";
var filePath = "/home/files/" + fileName;

fs.writeFile(filePath, data, function (err) {
    if (err) {
        //Error handling
    } else {
        console.log('Done');
        res.download(filePath, fileName, function(err) {
            console.log('download callback called');
            if( err ) {
                console.log('something went wrong');
            }

        }); // pass in the path to the newly created file
    }
});

Update

If you are using an ajax request, its not possible to download a file this way. Browsers make it impossible to make downloads through ajax requests.

What you will want to do is just use the url to download the file in an anchor element.

HTML

<a class="button" href="http://localhost:3000/openFile" target="_blank">Get request</a>

If you need to do it progmatically with javascript, you can use the window.open() method.

Javascript

$('.button').click(function(e) {
    e.preventDefault();
    window.open('http://localhost:3000/openFile', '_blank');
});

I used jQuery in this example but I think it illustrates what needs to be done. The window.open part is the important part.

Share:
11,878

Related videos on Youtube

arpit joshi
Author by

arpit joshi

Updated on June 04, 2022

Comments

  • arpit joshi
    arpit joshi almost 2 years

    I have my REST service in Java and it has a endpoint which sends a file to the client (HTTP GET, /file). My front end client is in NodeJS. I am not able to download the file from the REST service. I can only store the file at a particular location, but I want to have a download dialogue box where the user can store the file (just like any other download dialogue box). My NodeJS code is as below:

    router.get('/openFile',function(req,res){
        native_data_retrieval_rest_client.get("http://localhost:8080/file?fileName=presentation.pcap",function(data){
            var fileName="/home/files/presentation.pcap";
            res.download(data);//This doesnt open dialogue box 
    
            fs.writeFile(fileName, data, function (err) {
                if (err) {
                    //Error handling
                } else {
                    console.log('Done');
                }
            });
        });
    });
    

    The file is saved statically on the location /home/files/presentation.pcap.

    My REST service side response is like below:

    response.setHeader("Content-Disposition", "attachment; filename="
                        + fileName);
                response.setHeader("Content-Type", type);
    
                reportBytes = new byte[131072];// New change
                OutputStream os = response.getOutputStream();// New change
                int read = 0;
                while ((read = inputStream.read(reportBytes)) != -1) {
                    os.write(reportBytes, 0, read);
                }
                //System.out.println("Bytes sent" + reportBytes);
                os.flush();
                os.close();
    

    And the result which I get on the NodeJS side is just like an alert box with the file contents in it. See output below:

    enter image description here

    Can anyone please let me know what mistake I am doing here. I would like to have download dialogue box when the user clicks on the Download button. When clicking the download button, a call should go to the REST service which in turn will send the file to the NodeJS front end and a dialogue box will open, which will ask the user for the location.

    My Call from HTML is like below

    tr.append("td").append("button")
    .on("click", function(){
    
               openFile();
              })
    
     function openFile(){
              alert("button clicked");
    
              $http.get('/openFile/').success(function(response) {
                  console.log(response.response);
               }).error(function(error){
                  alert(error);
                });
    
              }
    
  • JoeMoe1984
    JoeMoe1984 over 7 years
    Are you seeing the "Done" log from your terminal?
  • arpit joshi
    arpit joshi over 7 years
    Yes I am able to see the done on the log .And also the file is stored at the static location.
  • JoeMoe1984
    JoeMoe1984 over 7 years
    The code is working for me. I adjusted the res.download parameters and added a callback function in case of an error. When you run that code do you see anything printed to the console "something went wrong"?
  • arpit joshi
    arpit joshi over 7 years
    did the same but no download box
  • arpit joshi
    arpit joshi over 7 years
    fs.writeFile(fileName, data, function (err) { if (err) { //Error handling } else { console.log('Done'); res.download(fileName,"presentation.pcap",function(error){ if(error){ console.log(error); }else{ console.log("downloaded"); } }); } });
  • JoeMoe1984
    JoeMoe1984 over 7 years
    Ok, Updated my answer. Ajax isn't really a possible solution so you will have to do it another way.