Puppeteer - PDFPrint but pdf is blank - node.js

I have a problem with puppeteer and pdf printing.
Everything looks ok, no error code,... but pdf is blank.
and templateHtml is good ! maybe it's an error in functions call await ?
Please help me !
async function createPDF(quotation, quoteurl, quotname){
var templateHtml = fs.readFileSync(path.join(process.cwd(), './templates/quotation2.html'), 'utf8');
//console.log(templateHtml);
var template = handlebars.compile(templateHtml);
//console.log(template);
var html = template(quotation);
//console.log(html);
var pdfPath = path.join(`${quoteurl}`, `${quotname}.pdf`);
console.log(pdfPath)
var options = {
width: '1230px',
headerTemplate: "<p></p>",
footerTemplate: "<p></p>",
displayHeaderFooter: false,
margin: {
top: "10px",
bottom: "30px"
},
printBackground: true,
path: pdfPath
}
const browser = await puppeteer.launch({
//args: ['--no-sandbox'],
headless: true
});
var page = await browser.newPage();
console.log('OH YES');
await page.goto(`data:text/html;charset=UTF-8,${html}`,{ waitUntil: ['domcontentloaded', 'load'] }).then(function (response) {
// page.emulateMedia('screen')
page.pdf({ path: pdfPath
, format: 'letter' })
.then(function (res) {
browser.close();
}).catch(function (e) {
browser.close();
})
})
}
i don't understand why it's not working.

I Change with this content and it works ! but the logo.png doesn't appear in the pdf (or it's in the same folder than html file.
Is there something to add to puppeteer to include image file in the pdf ? (it's declared in html file)
await page.setContent(html,{ waitUntil: ['domcontentloaded', 'load', "networkidle0"] }).then(function (response) {
// page.emulateMedia('screen')
page.pdf({ path: pdfPath,
format: 'A4',
printBackground: true,
margin: {
top: '20px',
bottom: '20px',
right: '20px',
left: '20px' }})
.then(function (res) {
browser.close();
}).catch(function (e) {
browser.close();
})
})

Related

Error while sending a pdf from Node.js server to Angular client

I try to send a pdf made by Puppeteer to my Angular client but I get this error:
The server-side code:
app.get('/convCVtoPDF',auth, jsonParser,async (req,res)=>{
const id = req.header('id')
const options = {
margin: {
top: '50px',
right: '50px',
bottom: '50px',
left: '50px',
},
pageSize: 'A4',
landscape: false,}
try {
const browser = await puppeteer.launch({"headless": true});
const page = await browser.newPage();
await page.setExtraHTTPHeaders({
'id':id
});
await page.goto('http://localhost:4200/BasicCvPDF');
const pdf = await page.pdf(options);
await browser.close();
// Send the PDF buffer in the response
res.setHeader('Content-Type', 'application/pdf');
res.send(pdf);
} catch (e) {
console.log(e);
res.status(500).send();
}
})
And the client side is:
async ngOnInit(){
await this.http.get<any>('http://localhost:3000/getUserById',{
headers:new HttpHeaders({'Content-Type':'application/json'})
}).toPromise()
}
I am sure the PDF is valid because If I specify a path for Puppeteer to save it, I can open and view it without a problem.
Any thoughts on why it can happen?

Puppeteer not work correctly with handlebars and get only blank page PDF

Hello im working in application that i want to create PDF files using puppeteer and handlbars but it create only blank PDF
Here is my code
File : functions.js
createPDF = async (templateName, data, file_name) => {
const pdfPath = `${process.cwd()}/public/tickets/${file_name}.pdf`;
const filePath = path.join(process.cwd(), "templates", `${templateName}.hbs`);
const html = fs.readFileSync(filePath, "utf-8");
const content = hbs.compile(html);
const htmlContent = content(data);
const options = {
format: "A4",
headerTemplate: "<p></p>",
footerTemplate: "<p></p>",
displayHeaderFooter: false,
margin: {
top: "10px",
bottom: "30px",
},
printBackground: true,
path: pdfPath,
};
const browser = await puppeteer.launch({
args: ["--no-sandbox"],
headless: true,
});
const page = await browser.newPage();
await page.goto(`data:text/html;charset=UTF-8,${htmlContent}`, {
waitUntil: "networkidle0",
});
console.log(await page.content());
await page.pdf(options);
await browser.close();
};
fileContoller.js
exports.myfile = async (req, res, next) => {
const { approved } = req.body;
const getData = await MyTable.findAll({
attributes: [
"id",
"first_name",
"last_name",
"birthday",
"gender",
"address",
"img",
],
where: { approved},
raw: true,
});
for (let i = 0; i < getData.length; i++) {
const createPDFforuser = await functions.createPDF(
"myhbsmockuptemplate",
getData[i],
`${getData[i].id}+${i}`
);
}
}
when i console.log htmlContent it get the html complete and correctly done as i write it
But when i console log awit page.content()
Here i dont get the html as expected it get only few line
<html><head>
<meta charset="utf-8">
<style type="text/css">
.tmp-mockup { font-family: "Staatliches", cursive; color: black;
font-size: 14px; letter-spacing: 0.1em; margin: 25px 0; } .ticket-box {
margin: auto; display: flex; background: </style></head><body></body></html>
Wait for some element in htmlContent after page is loaded.
await page.goto(`data:text/html;charset=UTF-8,${htmlContent}`, {
waitUntil: "networkidle0",
});
await page.waitForSelector('#visible-element')

Node.js Puppeteercannot render pdf export css correctly

I'm trying to get the html output of a website as a pdf with the width and height I specified with Node.js. However, on some sites, it can print without problems, while on some sites, the output is very distorted. I couldn't figure out why. When I turn on the handless feature and examine it, the page is created very smoothly, but in the pdf output, the images are corrupted like the pdf below. Can you please help? Where am I doing wrong?
https://pdfalarm.s3.eu-west-1.wasabisys.com/https%253a%252f%252frun-fix.com%252f30018001652834515056.pdf
const gopdf = async (url, width, height) => {
return new Promise(async (resolve, reject) => {
try {
var name = encodeURIComponent(String(url + width + height + Date.now()) + '.pdf')
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setViewport({ 'width': width, 'height': height });
await page.goto(url, { waitUntil: 'networkidle2' });
const optionsPDF = {
printBackground: true,
width: width + "px",
height: height + "px",
margin: { top: 0, right: 0, bottom: 0, left: 0 }
}
await delay(800)
const pdf = await page.pdf(optionsPDF);
await browser.close();
aws.upl(name, pdf)
.then(res => {
resolve({
status: res.data.Location?true:false,
data: res.data.Location?res.data.Location:false
})
})
} catch (err) {
resolve({
status: false,
data: err
})
}
})
}
If I put a wait time of 800 ms after the page is created, it looks corrupted as in the pdf in the link.

How to print something on every page on page.pdf

I need to setup an anchor tag on every page. Is that possible?
<a href='#toc'>toc</a>
I tried implementing it like this
async function printPDF(domain,filename){
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setViewport({ width: 600, height: 400 })
await page.goto(domain + '/docs/' + filename + '.html', {waitUntil: 'networkidle0'});
const pdf = await page.pdf({
format: 'A4',
scale : 1,
printBackground : true,
headerTemplate: "<a href='#toc'>toc</a>" ,
displayHeaderFooter : true,
margin: { top: "2cm", bottom: "2cm", left: "2cm", right: "2cm" }
});
await browser.close();
return pdf;
}
But it's not working. Maybe because the header is treated as seperate from the content so it's not detecting the anchor?

Giving timeout after evaluate in puppeteer is not working

I have a page which contains few visualizations. I have to evaluate and resize the charts. while evaluating, it takes few seconds to resize. the Previously I did this using phantom. I use to give timeout in the callback function and it worked perfectly. I'm trying the same using puppeteer which is not working. Not working in the sense, the resizing did not happen even after the timeout.
sample puppeteer code(not working)
const puppeteer = require('puppeteer');
const fs = require('fs');
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 2048, height: 1024 });
await page.goto("http://localhost:3000", { timeout: 180000 });
await timeout(5000);
page.on('console', msg => console.log('PAGE LOG:', msg.text()));
await page.evaluate(function() {
for (var i = 0; i < $('.react-grid-item').length; i++) {
$('.react-grid-item:eq(' + i + ')').css({
position: 'absolute',
height: '300px',
width: '100%',
top: (i * 300) + 'px',
left: '0px'
})
}
})
.then(function() {
setTimeout(function() {
page.pdf({
path: 'test' + new Date() + '.pdf',
// height: 7777,
// width: 2048,
format: 'a4',
displayHeaderFooter: false,
margin: {
top: "75px",
bottom: "75px"
}
});
// console.log(sum);
}, 5000);
}).catch(function(err) {
console.error(err);
})
})();
using await/async try follow like this:
await page.evaluate((a, b) => {
return a + b
}, 1, 2).then((sum) => {
setTimeout(() => {
console.log(sum)
}, 2000)
})

Resources