Javascript 使用Puppeter生成文件时,Pdf高度和宽度会发生变化

Javascript 使用Puppeter生成文件时,Pdf高度和宽度会发生变化,javascript,node.js,pdf,puppeteer,google-chrome-headless,Javascript,Node.js,Pdf,Puppeteer,Google Chrome Headless,我正在尝试从我的网站页面生成PDF。 为此,我有一台运行Puppeter的express服务器,它可以做以下几件事: -获取用户查看页面时浏览器的宽度。 -调整chrome无头浏览器的大小。 -计算页面的高度。 -将宽度/高度信息作为参数传递给page.pdf({}) 我网站的一些页面在一个页面上呈现得很好。但另一些则在两个页面上呈现,好像有些元素将内容高度推到高于在Puppeter上用javascript计算的高度 如果它确实有用,我想我在代码的开头使用了这个片段来掩饰自己:wait page

我正在尝试从我的网站页面生成PDF。 为此,我有一台运行Puppeter的express服务器,它可以做以下几件事: -获取用户查看页面时浏览器的宽度。 -调整chrome无头浏览器的大小。 -计算页面的高度。 -将宽度/高度信息作为参数传递给
page.pdf({})

我网站的一些页面在一个页面上呈现得很好。但另一些则在两个页面上呈现,好像有些元素将内容高度推到高于在Puppeter上用javascript计算的高度

如果它确实有用,我想我在代码的开头使用了这个片段来掩饰自己:
wait page.emulateMedia('screen')

我检查了几个假设: -使用调试控制台,我在调整页面大小时获得了文档的实际高度。 -我检查了一下这些信息是否正确地传递给了木偶演员。 -我通过将其转换为像素来检查以英寸为单位的高度是否正确

这三个假设是正确的

这是我的木偶师代码:

    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;
const page=wait browser.newPage();
等待页面。仿真媒体(“屏幕”);
//将窗口调整为客户端看到它时的宽度。
异步函数调整窗口大小(宽度、高度){
等待page.setViewport({height,width});
//窗口框架-可能取决于操作系统和WM。
身高+=85;
//任何标签。
const{targetInfo:[{targetId}]}=等待浏览器。\u connection.send(
'Target.getTargets'
);
//选项卡窗口。
const{windowId}=wait browser.\u connection.send(
'Browser.getWindowForTarget',
{targetId}
);
//调整大小。
等待浏览器。\u connection.send('browser.setWindowBounds'{
边界:{高度,宽度},
窗口ID
});
}
调整窗口大小(parseInt(请求正文证据宽度),0);//使用0作为默认高度,因为它是必需的,但不相关。
//等待实际更改页面宽度
wait page.mainFrame().waitForFunction(`window.innerWidth===${parseInt(req.body.evidenceWidth)}`);
//转到该页,等待该页上的所有连接被解析
wait page.goto(`${req.body.url}`,{waitUntil:'networkidle0'});
//计算实际页面高度
const realPageHeight=等待页面。评估(()=>{
const body=document.body,
html=document.documentElement;
const pageHeight=Math.max(body.scrollHeight、body.offsetHeight、html.clientHeight、html.scrollHeight、html.offsetHeight);
返回页面高度;
});
//将大小从像素转换为英寸,以避免木偶演员造成的舍入问题
const convertPixelToInches=(值)=>{
设英寸=数学单元(值/96*1000)/1000;
在`;中返回`${parseFloat(inches).toFixed(3)}//计算inches值并将其四舍五入。
}
常量pageWidth=转换像素到像素(请求正文证据宽度);
const pageHeight=转换像素到像素(realPageHeight{
如果(错误){
错误(`无法生成证据html`,错误);
}否则{
res.status(200).sendFile(join(\uuu dirname,HTML\u deception\u FD,`${uuid}.HTML`);
}
});
打破
案例“pdf”:
等待页面.pdf({
路径:join(\uuu dirname,PDF\u证据\u FD,`${uuid}.PDF`),
高度:页面高度,
宽度:页面宽度,
背景:是的,
});
res.status(200).sendFile(join(uu dirname,PDF u证据FD,`${uuid}.PDF`);
打破
违约:
res.status(501).send({error:'您选择的格式不受支持'});
打破
}
等待页面。关闭();
等待浏览器关闭();
});
app.on(“监听”,函数(){
console.log(“在端口%d上侦听”,应用程序端口);
});
返回应用程序;

还有!我注意到了另一个问题,假设我有一个750px的断点,我把800px传递给Puppeter,我希望这个断点不会在我的pdf中被击中。但是在pdf中进行的渲染就像页面宽度在断点下一样。pdf生成过程中是否添加了一些看不见的空白?

因此,经过几天的搜索,我发现了以下问题:

  • 我在css中使用rem表示字体大小和行高,所以我删除了它们 从被指控的分子那里
  • 我没有重置css,在我的页面顶部添加normalize.css 样式解决了我大部分的身高问题
  • 即使使用normalize.css,Chrome也在周围添加了rem填充 在段落中,我添加了一个以像素为单位的值