arpit joshi
arpit joshi

Reputation: 2134

File download from server in NodeJS

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);
            });

          }

Upvotes: 4

Views: 14572

Answers (1)

JoeMoe1984
JoeMoe1984

Reputation: 2032

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.

Upvotes: 5

Related Questions