Pdf size issue in node js using puppeteer?

huangapple go评论58阅读模式
英文:

Pdf size issue in node js using puppeteer?

问题

我有一个包含数据的HTML内容,我正在使用puppeteer npm包将其转换为PDF。我能够生成PDF,但PDF的大小不是全尺寸的。它生成了一个小尺寸的PDF,周围有很多多余的空间。

如截图所示,左侧和顶部有很多空白,PDF没有填满整个页面。我已经尝试了页面大小为A4、A6,但仍然存在相同的问题。请建议应该怎么做?

Pdf size issue in node js using puppeteer?

英文:

I am having a HTML Content with data and i am converting it to PDF using puppeteer npm package. I am able to generate PDF but the PDF is not full size. It's generating a small size pdf which is having lot of extra space around.

        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 size issue in node js using puppeteer?

As in screenshot there is lot of gap in left and top and pdf is not filled to page. I have tried pagesize a4,a6 but still same issue. Please suggest what to do ?

答案1

得分: 1

  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 });
...
英文:
  1. To debug, try capturing your page screen to make sure the margins were not generated before exporting to pdf:
await page.screenshot({ path: '/tmp/sample.png', fullPage: true });
  1. I think you're trying to put a vertical invoice (letter format) into a horizontal landscape page which can cause unexpected margin issue, changing landscape mode may fix your problem (vertical = landscape: false)
...
const pdf = await page.pdf({ scale: 1.0, height: height + 'px', width: width + 'px', printBackground: true, landscape: false });
...

答案2

得分: 0

出于调试目的,也许可以尝试直接连接到提供发票HTML的节点服务器,并使用Chrome手动执行打印操作以查看发生了什么。

Puppeteer将使用CDP API,可能会使用Page.printToPDF方法,可以查看此处的相关信息。

请注意,还有其他参数,特别是formatpreferCSSPageSize可能对您进行测试很有趣。例如,根据发票接收方所在的地区,可以使用format: 'A4'format: 'Letter'

但最终生成的PDF将基于HTML文档的CSS。因此,您应该将HTML和body的宽度设置为100%,看看是否会产生差异。

在这里,手动测试是最合理的选择。您可以在开发者工具中的“更多工具”>“渲染”中,将媒体类型强制设置为打印而不是屏幕,以查看打印样式的效果,因为这将用于PDF渲染。

Pdf size issue in node js using puppeteer?

我不确定为什么在启动参数中要使用全屏模式。如果没有充分的理由,建议删除它。

如果您正在以无头模式运行,请禁用它并将await browser.close();注释掉,以使浏览器窗口保持打开状态。然后,您可以直接在保留的窗口中调试样式。

我还注意到您告诉PDF API提供LANDSCAPE(横向排列)。根据您的发票外观,我猜这是错误的。

我建议避免使用屏幕截图API,因为存在一些问题:

  • 由于PDF是从图像而不是HTML创建的,您将失去可选择/可搜索的文本。
  • 屏幕截图API默认捕获整个视口的截图,因此您必须进行一些调整以正确设置视口,如果您的样式不是基于缩放到100%宽度,可能会遇到相同的问题。视口设置在某些系统上无法在无头和非无头模式之间一致工作(对于相同的代码,无头模式和非无头模式会生成不同大小的屏幕截图)。
英文:

For debugging, maybe try to just connect to your node server that serves the invoice HTML directly with chrome and do a print to PDF manually to see what happens.

Puppeteer is going to be using CDP apis. Likely Page.printToPDF.

Note there are other parameters there, in particular format or preferCSSPageSize might be interesting for you to test. e.g. format: 'A4' or format: 'Letter' depending on whether your invoice recipient is in Europe or the US.

But ultimately the PDF you are getting is going to be based on the CSS for your html document. So you should set your html/body width to 100% and see if that makes a difference.

Manual testing makes the most sense here. You can (devtools > more tools > rendering) force the media type to be print rather than screen to also see how your print styles look as that is what will be used for the PDF rendering.

Pdf size issue in node js using puppeteer?

I'm not sure why you have fullscreen in your launch arguments. If you don't have a good reason, I would remove that.

If you are running headless, disable that and comment out the await browser.close(); so the browser window sticks around. You can then debug your styles directly in the window that remains.

I also see you are telling the pdf api to give you LANDSCAPE. Based on how your invoice looks I would guess that is wrong.

I would stay away from the screenshot API as there are a couple issues there:

  • you lose the selectable/searchable text because the PDF is made from an image rather than html.
  • the screenshot API defaults to taking screenshot of the entire viewport so you have to play games to get the viewport set right and you may have the same problem if your styles aren't based on scaling up to 100% width. The viewport setting also doesn't work consistently between headless and non-headless modes on some systems (you get different size screenshots in headless than non-headless mode for the same code).

huangapple
  • 本文由 发表于 2023年6月1日 19:14:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76381299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定