I'm building a client-server certificate generator.
On Backend I'm using two endpoints:
/
- Receives a JSON containing data extracted from inputs, sanitize them, and returns if they're valid or not
/download
- Receives whether data is valid or not. If it's, generate a
certificate.pdf
file and responses it withres.download(certificatePath)
- I guess I should use some kind of token/authentication/authorization because someone could just ignore the first endpoint but I'll do that once the downloading itself is fixed
I think the problem with backend is in some of those functions:
const getCertificatePDF = (name, validValuesData, validValuesQty, response) => {
// ... ommited for brevity
pdf.create(document, options)
.then(res => {
console.log(res)
let filePath = path.join(__dirname, 'certificate.pdf');
console.log("FILE PATH: ", filePath);
response.download(filePath, "certificate.pdf");
})
.catch(error => {
console.error(error)
});
}
app.post('/download', (req, res) => {
const data = req.body;
console.log("DATA", data);
getCertificatePDF(data.name, data.validValuesData, data.validValuesQty, res)
});
On frontend, I chained both requisitions using promises, created a blob
, created a link with download
attribute for that blob
and triggered anonClick
:
const sendForm = (filledCodeValues, email, name) =>{
// ...ommited for brevity
fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: data,
})
.then((res) => res.json())
.then((processedData) => {
alertAllFilledInvalid(processedData.validValuesQty)
const dataString = JSON.stringify(processedData);
if(processedData.validValuesQty > 0){
console.log("DATA STRING ", dataString)
const downloadUrl = url "download";
fetch(downloadUrl, {
method: "POST",
headers: {
'Content-Type': 'application/json',
},
body: dataString,
})
.then((res2) => {
res2.blob()
})
.then((blob)=>{
const newBlob = new Blob([blob]);
const newUrl = window.URL.createObjectURL(newBlob);
const link = document.createElement('a');
link.href = newUrl;
link.setAttribute('download', 'certificate.pdf');
document.body.appendChild(link);
link.click();
link.parentNode.removeChild(link);
window.URL.revokeObjectURL(newBlob);
})
}
})
}
Issue
The issue is, the certificate.pdf
downloaded by frontend is containing undefined
:
I know the first request is correct, because the console.log()
is printing the expected contents for stringData
:
I also know the second request work, because on backend, certificate.pdf is being correctly generated:
Ps - i'm manually deleting certificate.pdf
on backend to ensure it's a new one generated
Since certificate is being generated, I believe there's something wrong with either:
- Backend's
response.download(filePath, "certificate.pdf");
- FrontEnd blob creating and downloading
I manually moved certificate(25).pdf
(generated by frontend) to backend and run a script for reading both certificate.pdf
(generated by backend) files, to test if the issue is on filePath
using a readFiles.js
script:
const fs = require('fs');
let path = require('path');
let filePath = path.join(__dirname, 'certificate.pdf');
console.log("FILE PATH: ", filePath);
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(">>>>> FilePath content <<<<< ", data);
});
let filePath2 = path.join(__dirname, 'certificate(25).pdf');
console.log("FILE PATH 2: ", filePath2);
fs.readFile(filePath2, 'utf8', (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(">>>> FilePath2 content <<<< ", data);
});
It turns out the path is correct, and certificate.pdf (backend)
has content, while certificate(25).pdf (frontend)
has just an undefined
value.
Can someone help me please?
CodePudding user response:
You need to return the value of res2.blob()
:
.then((res2) => {
return res2.blob()
})
Or leave out the brackets:
.then((res2) => res2.blob())