I added to my NodeJS API an endpoint to be able to generate and download a PDF using the library PDFMake. I'm able to generate and upload the PDF on the server-side but on browser site, the PDF is downloaded and failed with 0 KBytes on it and I stack trying to find a solution for it.
I understood that the file is downloaded before the writeStream
finish to write it but adding an extra function as like:
pdf.on("finish", async () => {
res.download(pdf);
res.send("PDF generated");
});
This didn't help but added an extra error of:
UnhandledPromiseRejectionWarning: RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: undefined
I have no idea how to solve this and hope for help. Most probably is something I'm missing.
The code responsible for the functionalities are: Router
router.get("/pdf/all", async (req, res) => {
const movies = await movie.getMovies();
try {
const pdf = await generatePdf(movies, "all");
pdf.on("finish", async () => {
res.download(pdf);
res.send("PDF generated");
});
} catch (err) {
// Errors
res.status(err.status).json({ message: err.message });
throw new Error(error.message);
}
});
generatePdf
const generatePdf = (movies, name) => {
return new Promise((resolve, reject) => {
try {
let fonts = {
Roboto: {
normal: "Helvetica",
bold: "Helvetica-Bold",
italics: "Helvetica-Oblique",
bolditalics: "Helvetica-BoldOblique"
}
};
let printer = new pdfMaker(fonts);
const pdfTemplate = template(movies);
const pdfStream = printer.createPdfKitDocument(pdfTemplate, {});
const filePath = path.join(
__dirname,
uploads + "/" + pdfDir + `${name}.pdf`
);
console.log(filePath);
pdfStream.pipe(writeStream(filePath));
pdfStream.end();
resolve(filePath);
} catch (err) {
console.log(err);
reject(err);
}
});
};
I would suggest you try the following code for generatePdf
:
const generatePdf = (movies, name) => {
return new Promise((resolve, reject) => {
try {
let fonts = {
Roboto: {
normal: "Helvetica",
bold: "Helvetica-Bold",
italics: "Helvetica-Oblique",
bolditalics: "Helvetica-BoldOblique"
}
};
let printer = new pdfMaker(fonts);
const pdfTemplate = template(movies);
const pdfStream = printer.createPdfKitDocument(pdfTemplate, {});
const filePath = path.join(
__dirname,
uploads + "/" + pdfDir + `${name}.pdf`
);
console.log(filePath);
let stream = pdfStream.pipe(writeStream(filePath));
stream.on('finish', function(){
pdfStream.end();
resolve(filePath);
}
} catch (err) {
console.log(err);
reject(err);
}
});
};
The code should wait for the pdfStream.pipe
to finish before finishing the file and resolving
the filePath
Also you cannot use res.send
after res.download
as the download sets the response to be the file and you can no longer send another response to the client.