使用puppeteer的node js中的Pdf大小问题?

e5njpo68  于 2023-06-22  发布在  Node.js
关注(0)|答案(2)|浏览(273)

bounty明天到期。回答此问题可获得+100声望奖励。TechChain希望引起更多关注这个问题。

我有一个HTML内容与数据,我将其转换为PDF使用puppeteer npm包。我可以生成PDF,但PDF不是全尺寸的。它生成的是一个小尺寸的PDF,周围有很多额外的空间。

res.render('invoice-pdf', { response: { data: invoiceInfo } }, async (error, resp) => {
            const getPDF = async (cData: any) => {
                return new Promise(async (resolve, reject) => {
                    const browser = await puppeteer.launch({ headless: 'new', args: ['--start-fullscreen']});
                    const page = await browser.newPage();
                    await page.setContent(cData);
                    
                    const height = await page.evaluate(() => document.documentElement.offsetHeight);
                    const width = await page.evaluate(() => document.documentElement.offsetWidth);

                    console.log('Height', height);
                    const pdf = await page.pdf({ scale: 1.0, height: height + 'px', width: width + 'px', printBackground: true, landscape: true });
                    await browser.close();
                    resolve(pdf);
                });
            };
            const details: any = await getPDF(resp);
            res.header('Content-type', 'application/pdf');
            res.header('Content-disposition', `attachment;filename=invoice-${req.params.invoiceId}.pdf`);
            res.send(details.toString('base64'));

在屏幕截图中,左侧和顶部有很多间隙,PDF没有填充到页面。我试过A4,A6的页面大小,但仍然是同样的问题。请建议该怎么做?

oyt4ldly

oyt4ldly1#

1.要进行调试,请尝试捕获页面屏幕,以确保在导出为pdf之前未生成边距:

await page.screenshot({ path: '/tmp/sample.png', fullPage: true });

1.我想你是想把一个垂直的发票(字母格式)到一个水平的横向页面,这可能会导致意想不到的保证金问题,改变横向模式可能会解决你的问题(垂直= landscape: false

...
const pdf = await page.pdf({ scale: 1.0, height: height + 'px', width: width + 'px', printBackground: true, landscape: false });
...
mbyulnm0

mbyulnm02#

对于调试,也许可以尝试直接连接到您的节点服务器,该服务器直接使用chrome提供发票HTML,并手动打印到PDF,看看会发生什么。
Puppeteer将是using CDP api。可能是Page.printToPDF
注意,这里有other parameters,特别是formatpreferCSSPageSize,您可能会对测试感兴趣。例如format: 'A4'format: 'Letter',具体取决于您的发票收件人是在欧洲还是在美国。
但最终你得到的PDF将基于HTML文档的CSS。所以你应该将html/body宽度设置为100%,看看这是否有区别。
手动测试在这里最有意义。您可以(devtools > more tools > rendering)强制媒体类型为打印而不是屏幕,以查看您的打印样式的外观,因为这将用于PDF渲染。

我不知道为什么你在你的启动参数中有全屏。如果你没有一个好的理由,我会删除它。
如果你正在运行headless,禁用它并注解掉await browser.close();,这样浏览器窗口就不会消失。然后,您可以直接在剩余的窗口中调试样式。
我还看到你在告诉pdf API给予你景观。根据你的发票看起来,我猜这是错误的。
我会远离截图API,因为那里有几个问题:

  • 你失去了可选择/可搜索的文本,因为PDF是从图像而不是HTML制作的。
  • 截图API默认为整个视口的截图,所以你必须玩游戏来获得正确的视口设置,如果你的样式不是基于100%宽度的缩放,你可能会遇到同样的问题。在某些系统上,在无头模式和非无头模式之间,视口设置也不一致(对于相同的代码,在无头模式和非无头模式下,您会得到不同大小的屏幕截图)。

相关问题