我正在尝试从我的网站页面生成 pdf。
为此,我有一个运行 Puppeteer 并做几件事的快速服务器:
- 取用户查看页面时浏览器的宽度。
- 调整 chrome headless 浏览器的大小。
- 计算页面的高度。
- 将宽度/高度信息作为参数传递给 page.pdf({})
。
我网站的一些页面在一页上呈现得很好。但其他人确实在两个页面上呈现,就好像某些元素将内容高度推到高于 Puppeteer 上 javascript 计算的高度。
如果确实有帮助,我想我可以通过在我的代码开头使用这个片段来掩护自己:await page.emulateMedia('screen');
。
我检查了几个假设: - 使用调试控制台,我在调整页面大小时得到了文档的实际高度。 - 我检查了此信息是否已正确传递给 Puppeteer。 - 我通过将其转换为像素来检查以英寸为单位的高度是否正确。
这三个假设是正确的。
这是我的 Puppeteer 代码:
const page = await browser.newPage();
await page.emulateMedia('screen');
// Resize window to the width it had when the client has seen it.
async function resizeWindow(width, height) {
await page.setViewport({height, width});
// Window frame - probably OS and WM dependent.
height += 85;
// Any tab.
const {targetInfos: [{targetId}]} = await browser._connection.send(
'Target.getTargets'
);
// Tab window.
const {windowId} = await browser._connection.send(
'Browser.getWindowForTarget',
{targetId}
);
// Resize.
await browser._connection.send('Browser.setWindowBounds', {
bounds: {height, width},
windowId
});
}
resizeWindow(parseInt(req.body.evidenceWidth), 0); // Use 0 as a default height because it is required, but not relevant.
// Wait for page width to be actually changed
await page.mainFrame().waitForFunction(`window.innerWidth === ${parseInt(req.body.evidenceWidth)}`);
// Go to the page and wait for all the connection on the page to be resolved
await page.goto(`${req.body.url}`, {waitUntil: 'networkidle0'});
// Calculate real page height
const realPageHeight = await page.evaluate(() => {
const body = document.body,
html = document.documentElement;
const pageHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight );
return pageHeight;
});
// Convert size from pixel to inches to avoid rounding issues caused by Puppeteer
const convertPixelToInches = (value) => {
let inches = Math.ceil(value/ 96 * 1000) / 1000;
return `${parseFloat(inches).toFixed(3)}in`; // Calculate inches value and round it up.
}
const pageWidth = convertPixelToInches(req.body.evidenceWidth);
const pageHeight = convertPixelToInches(realPageHeight < req.body.evidenceHeight ? req.body.evidenceHeight : realPageHeight);
// Send the response
switch(req.body.format) {
case 'html':
const html = await page.content();
await fs.writeFile(join(__dirname, HTML_EVIDENCE_FD, `${uuid}.html`), html, (err) => {
if (err) {
console.error(`Evidence html could not be generated`, err);
} else {
res.status(200).sendFile(join(__dirname, HTML_EVIDENCE_FD, `${uuid}.html`));
}
});
break;
case 'pdf':
await page.pdf({
path: join(__dirname, PDF_EVIDENCE_FD, `${uuid}.pdf`),
height: pageHeight,
width: pageWidth,
printBackground: true,
});
res.status(200).sendFile(join(__dirname, PDF_EVIDENCE_FD, `${uuid}.pdf`));
break;
default:
res.status(501).send({ error: 'The format you chose is not supported'});
break;
}
await page.close();
await browser.close();
});
app.on("listening", function() {
console.log("Listening on port %d", app.port);
});
return app;
还有!我注意到另一个问题,说我在 750px 处有一个断点,我将 800px 传递给 Puppeteer,我希望我的 pdf 中不会遇到该断点。但是在 pdf 中完成的渲染就像页面宽度在断点下一样。在 pdf 生成过程中是否添加了一些不可见的边距?
最佳答案
经过几天的搜索,我发现了问题:
- 我在 css 中使用 rem 作为字体大小和行高,所以我删除了它们 与犯罪分子有关。
- 我没有重置 css,在我的顶部添加 normalize.css 样式解决了我的大部分高度问题。
- 即使使用 normalize.css,Chrome 也会在周围添加 rem 填充 段落,我添加以设置一个以像素为单位的值。
关于javascript - 使用 Puppeteer 生成文件时 Pdf 高度和宽度发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51549625/