Reputation: 2134
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:
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
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