I have an application which is developed with node.js and hosted on heroku. We are generating a pdf on the node.js server and sending the stream to frontend, so that the users can download the file.
When i am trying it on the localhost, i am able to see proper content in the file. But when i host the node.js code on heroku and try the same, the file is not showing local language(telugu, an indian language) in the pdf. Below is the screenshot of the file i am getting.
The below code is the frontend code which will hit the server api and get the file content from server
const response = await axios.post(
'/reports/pdf',
{ tests: this.tests },
{ responseType: 'blob' },
);
window.console.log(response);
if (response) {
this.createAndDownloadBlobFile(response, 'tests');
}
The below code is to download the file. This function is called in the above code after getting the response.
createAndDownloadBlobFile(body, filename, extension = 'pdf') {
const blob = new Blob([body]);
const fileName = `${filename}.${extension}`;
if (navigator.msSaveBlob) {
// IE 10+
navigator.msSaveBlob(blob, fileName);
} else {
const link = document.createElement('a');
// Browsers that support HTML5 download attribute
if (link.download !== undefined) {
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', fileName);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
},
The node.js code is as below
return new Promise((resolve, reject) => {
pdf
.create(document, options)
.then((res) => {
var content = fs.readFileSync(path.resolve(__dirname, '../utils/output.pdf'));
resolve(content);
})
.catch((error) => {
reject(error);
});
});
I tried few different ways by changing the response format to base64 and changing the data format. But still no use. Any help would be really appreciated.
Related
I am trying to download a file from my nodeJS server, however opening the files afterwards is not possible. For example: The original 15kb JPG file will be 24kb when downloaded and impossible to show.
upload:
if (fs.existsSync(filePath)) {
res.download(filePath);
readStream.pipe(res);
} else {
return res.status(404).json({msg: "Failed to load file"});
}
download:
import fileDownload from "js-file-download";
const getFile = async (filename) => {
const headers = {
'responseType': 'blob',
'x-access-token': JSON.parse(localStorage.getItem('user')).token
}
await axios.post(getFileRoute, {
filename: filename
}, {headers: headers})
.then((response) => {
fileDownload(response.data, filename);
});
}
The picture preview is also shown in the network tab of google chrome's inspect. Thank you for your help!
On the controller I return a path to where the excel file is located..Now I want to download that file
Below is my code:
reportExcel(val) {
axios
.get("/algn/api/report/" + val)
.then((res) => {
var url = res.data; // http://localhost.local/public/files/data.xlsx
const a = document.createElement("a");
a.href = url;
a.download = url.split("/").pop();
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
})
.catch((error) => {
console.log(error);
});
},
I am getting the error as "Excel cannot open the file "data.xlsx" because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file". (The original excel file is still usable).
I have tried all the solutions which I found in google but nothing worked. Please help. Thanks
Try this:
reportExcel(val) {
axios
// add responseType
.get("/algn/api/report/" + val, {responseType : 'blob'})
.then((res) => {
const url = window.URL.createObjectURL(new Blob([res]));
const a = document.createElement("a");
a.href = url;
const filename = `file.xlsx`;
a.setAttribute('download', filename);
document.body.appendChild(link);
a.click();
a.remove();
})
.catch((error) => {
console.log(error);
});
},
Assuming the link gives correct excel file, we can inform that it is file (not the usual JSON) by specifying {responseType : 'blob'} in the request. Then, create the file using window.URL.createObjectURL(new Blob([res])). The rest is small adjustments to handle file instead of text.
I'm struggling to download an Excel file in xlsx format in my Vue.js application. My Vue.js application make post request to the Node.js application which download that Excel file from remote SFTP server. Backend application works without any problems.
In Vue.js application I use next code:
axios.post(config.backendHost + '/excel', {
file_name: fileName
}).then((response) => {
const url = URL.createObjectURL(new Blob([response.data], {
type: 'application/vnd.ms-excel'
}))
const link = document.createElement('a')
link.href = url
link.setAttribute('download', fileName)
document.body.appendChild(link)
link.click()
});
After downloading file by browser, file opens automatically and I am experiencing an error that looks like this:
We found a problem with some content .xlsx. Do you want us to try and recover as much as we can?
You need to add the response type as a third argument in your post call
{
responseType: 'blob'
}
Your final code like that
axios.post(config.backendHost + '/excel', {
file_name: fileName
}, {
responseType: 'blob'
}).then((response) => {
const url = URL.createObjectURL(new Blob([response.data], {
type: 'application/vnd.ms-excel'
}))
const link = document.createElement('a')
link.href = url
link.setAttribute('download', fileName)
document.body.appendChild(link)
link.click()
});
Or you can use the library FileSaver.js to save your file
import FileSaver from 'file-saver'
axios.post(config.backendHost + '/excel', {
file_name: fileName
}, {
responseType: 'blob'
}).then((response) => {
// response.data is a blob type
FileSaver.saveAs(response.data, fileName);
});
my case worked:
axios.get(`/api/v1/companies/${companyId}/export`, {
responseType: 'blob',
}).then((response) => {
const url = URL.createObjectURL(new Blob([response.data]))
const link = document.createElement('a')
link.href = url
link.setAttribute(
'download',
`${companyId}-${new Date().toLocaleDateString()}.xlsx`
)
document.body.appendChild(link)
link.click()
})
I have requirement in my project with which when user select multiple file to download, we need to zip them and then make them to download. We have tested that the Struts2 action is listing all the file correctly and passing them to the UI. We've verified that the files are list on to UI correctly but when the blob statement executed, it made the zip file corrupted.
Here is the my code snippet.
Can anyone please help here?
Code:
$.ajax({
url: url,
data: data,
type: "POST",
async: true,
success: function (data) {
var binaryData = [];
binaryData.push(data);
var link=document.createElement('a');
link.href =window.URL.createObjectURL(**new Blob(binaryData, {type: "application/zip"**}));
link.download = "User Reports Data Files.zip"
link.click();
},
error: function (request, status, error) {
}
});
Two answers for you:
I don't think you can reliably download binary data with jQuery's ajax function (but I could be mistaken). If you want to download binary, use fetch, which has support for reading the response as a BLOB built in.
It would be simpler to have a zero-height iframe on your page with name="download-target" and then have a form target="download-target method="post" and submit that instead of using ajax. Be sure the response includes a Content-Disposition header, for instance:
Content-Disposition: attachment; filename="User Reports Data Files.zip"
#2 is simpler and lets the browser handle the download in its normal, thoroughly-tested way.
But here's a sketch of #1:
fetch(url, {
method: "POST",
body: data
})
.then(response => {
if (!response.ok) {
throw new Error("HTTP status " + response.status);
}
return response.blob();
});
.then(blob => {
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = "User Reports Data Files.zip"
link.style.display = "none"; // Firefox wants this
document.body.appendChild(link); // ""
link.click();
setTimeout(() => { // ""
document.body.removeChild(link); // ""
}, 10000); // ""
})
.catch(error => {
// Handle/report the error
});
Server Side
I trying to send file from NodeJs
/**
* Exports data to PDF format route.
*/
app.post('/export/pdf', upload.single('imageBlob'), function (request, response) {
var PDF = require('./services/PdfService').PDF;
var fileUrl = PDF.generatePDFExport(request.body, request.file.buffer);
setTimeout(() => {
response.sendFile(fileUrl);
}, 200);
});
This piece of code creates a valid pdf file (I can open it browsers URL hit file)
But some browser hides the pop-up window and I wanted to download a file instead of opening it.
I check response in client and it is some BLOB looking response.
Client Side
I try to create a file from the response but there is only an empty pdf file.
return axios.post('http://172.18.0.2:8001/export/pdf', formData).then(response => {
let blob = new Blob([response.data]);
FileSaver.saveAs(blob, "st-seatmap-shop.pdf");
})
What is a mistake here? On the server side with a sending file or on the client with saving file?
The only problem was in sending a request to the server.
Server by default returns stream and for saving file on client response needs to be a BLOB so I just updated request.
let requestOptions = {
responseType: 'blob'
};
return axios.post('http://172.18.0.2:8001/export/pdf', formData, requestOptions).then(response => {
let blob = new Blob([response.data]);
FileSaver.saveAs(blob, "st-seatmap-shop.pdf");
}).catch(error => {
console.log("error.response is : ", error);
});