I am trying to figure out the best way to convert multiple HTML strings to PDFs (client side), add those to a .zip file (preferably using JSZip) and then downloading that .zip file.
Here is some code to try and accomplish this...
// HTML examples to render
var tableHtml = `<table>
<tr>
<th>Company</th>
<th>Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Germany</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Mexico</td>
</tr>
</table>`
var boldHtml = "<p> Hello <strong>World</strong> </p>"
var imageHtml = `<h1> City </h1>
<img src="https://images.unsplash.com/photo-1582010905429-bef463482aa2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1000&q=80">`
var htmlToConvert = [tableHtml, boldHtml, imageHtml];
// Convert (using jsPDF, but totally open to other options... As this doesn't work)
let fileNumber = 1;
for (const html of htmlToConvert) {
let jsPdf = new jsPDF();
jsPdf.html(html); // This right here seems to be what I can't get working...
zip.file(`file${fileNumber}.pdf`, jsPdf.output('blob'), { binary: false });
fileNumber++;
}
// Save .zip file
const blob = await zip.generateAsync({ type: 'blob' });
const fileSaver = await import('file-saver');
fileSaver.default.saveAs(
blob,
`example.zip`
);
This code doesn't work, I think it's specifically the line jsPdf.html(html)
that doesn't work. Once the .zip downloads there are 3 PDF files, but they are all blank with no content.
If I replace jsPdf.html(html)
with jsPdf.text(html, 1, 1)
that seems to work, but it's just plain html, so nothing is rendered. I did take a look at this SO post and downgraded accordingly, but with no luck.
"html2canvas": "1.0.0-alpha.12",
"image-conversion": "^2.1.1",
jsPdf.html does have a callback option on it, so I also tried the following code:
pdf.html(document.body, {
callback: function (pdf) {
zip.file(`file${fileNumber}.pdf`, pdf.output('blob'), { binary: false });
}
});
However, the problem here is that the callback probably isn't being triggered until after the zip file saves, so the .zip will just be empty. Not sure exactly how to utilize the callback in this case? I might just be missing something obvious here.
I am open to using tools other than jsPdf to accomplish this task, any ideas?
Thank you! :)
The issue is that you need to wait for the all the conversions to complete before you save the zip file. You can do this by wrapping the callback in a Promise in order to work with your existing await
s:
await Promise.all(htmlToConvert.map((html, fileNumber) => {
const jsPdf = new jsPDF();
return new Promise<void>((resolve, reject) => {
jsPdf.html(html, {
callback: function (pdf) {
zip.file(`file${fileNumber}.pdf`, jsPdf.output("blob"), { binary: false });
resolve(); // maybe reject if jsPdf is able to signal some kind of error condition?
},
});
})
}));