Closed lukawal-miller closed 4 years ago
Was checking the plugin at you are correct, it doesn't work. And this is because the backend (the code that generates the PDF using Webkit) is working as a singleton, basically the way your are using the plugin to make concurrent drawing request is not supported, sorry :(.
Solution 1: you can make a print queue, basically you need to go one by one, take first member, transform into pdf, get base64, then you take the second, transform into pdf and so on.
Solution 2: Modify the plugin to support concurrent HTML to PDF transformation, it will require make a new Thread per Webkit per call, at the moment I don't have enough time to dedicate to this project.
But if you feel strong, I'll be glad to incorporate your contributions.
Thanks for your reply. Unfortunately I do not have time and enough knowledge to modify the plugin and solution 1 is not what I'm looking for. Hoping that someone else might update your plugin in near future.
Hi @cesarvr - I work with @lukawal-miller and wanted to pick this thread up. Can I ask for more info about what you mean by print queue?
In our code when we call the fromData()
function multiple times, it succeeds on the first call but fails on the second, so I'm not sure how your proposed solution would work? Any steer you could give me here would be much appreciated!
bengrah
Hi @lukawal-miller , basically the backend (which is singleton WebKit) requires time to finish the transformation of HTML to PDF, because of its singleton nature, if you pass multiple URL's and don't allow no enough time to finish rendering then it will only render the last URL. If you use something like Promise.all
it will fail.
What I suggest is that you basically queue the work manually, you pick one element transform it get your base64
, then go to the next and so on.
You can chain promises like in this example:
let urls = ['url1', 'url2']
pdf.fromURL({url: urls[0]})
.then(base64 => doSomethingWithIt(base64))
.then(() =>{
return pdf.fromURL({url:urls[1]})
})
.then(base64 => /* and so on..*/ )
Cheers, César.
Hi @cesarvr
Thanks for that - I think you're operating under the idea we know exactly how many PDFs we're going to generate each time.
Our use case is, the user selects from a checklist what kind of items they want to generate. For example, the user has a list of trades to choose from - they tick which trade that want to generate a PDF for:
Plumber [ ] Joiner [x] Roofer [x] Cleaner [x] Gardener [ ]
In our example, we've ticked three items, but it could be 4, 5, 1 etc. From what I can see in your example, you'd have to know exactly in the code how many you're going to do each time - would that be correct?
bengrah
Well I just wanted to give you an idea of how to solve the problem and overcome the plugin limitation, if your case evolves around a dynamic array then you could write an recurrent algorithm similar to this:
function makePDFRecursively(URLs){
if( URLs.length > 0 ) {
return false
}
return pdf.fromURL({url: URLs.pop()})
.then(base64 => doSomethingWithIt(base64))
.then(() =>{
return makePDFRecursively(URLs)
})
let urls = ['url1', 'url2']
makePDFRecursively(urls)
Hi @cesarvr
Thanks for your help on this one. Thanks to your suggestions we were able to resolve our issue by using the following code:
async function generateMultiplePDF() {
let htmlArray = ['<h1>Hello 1</h1>', '<h1>Hello 2</h1>'];
let base64Array = [];
let options = {
documentSize: 'A4',
type: 'base64'
}
for (let i = 0; i < htmlArray.length; i++) {
await pdf.fromData(htmlArray[i], options).then((base64) => {
base64Array.push(base64)
});
}
return base64Array;
}
Thanks again for your help and this plugin!
I am trying to generate multiple base64 files but have no luck.
Expected output should be an Array: [base64, base64, base64] But it looks like it stuck after first Promise and never completes.
Anyone can help me to find a solution to this?