javascript - 使用 Puppeteer 生成文件时 Pdf 高度和宽度发生变化

标签 javascript node.js pdf puppeteer google-chrome-headless

我正在尝试从我的网站页面生成 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/

相关文章:

html - 使 html 按钮不会触发 node.js 中的 app.post

ios - 在 Swift 中在 UIWebView 上方绘制

c# - Android,尝试在 Xamarin Android 应用程序中查看 PDF

ruby - 使用 Prawn PDF 跨多个页面的边界框

javascript - Facebox 只能使用一次

javascript - 我如何判断滚动条是否已到达帖子内容的末尾?

node.js - Node 、 express 、 Jade : How to process form data

post - POST 数据中的 node.js 和 utf-8

javascript - 包含特定版本的 JQuery 和插件而不与页面的 JavaScript 库冲突?

javascript - 数据属性中的逗号不起作用