【问题标题】:How can I change paper size in headless Chrome --print-to-pdf如何在无头 Chrome 中更改纸张尺寸 --print-to-pdf
【发布时间】:2017-12-11 17:06:24
【问题描述】:

我正在使用无头 Chrome 将 html 文档导出为 pdf

google-chrome --headless --disable-gpu --print-to-pdf='output_path' 'url'

如何更改生成的 pdf 中的纸张大小?

我可以控制 Chrome 参数和 html。

我总是收到美国信函。

没有记录在案的命令行选项。

我尝试设置 CSS:@page {size: A4;}。在无头模式下无效,但在正常模式下按 Ctrl+P 时有效(为Save as pdf 选择纸张大小的选项消失,导出的 pdf 具有 A4 页面大小) .

我已在 Ubuntu 16.04 上的 Chrome 版本 59、60 和 61 上尝试过此操作。

【问题讨论】:

  • 我已经检查了 Chromium 源代码。据我了解,也没有未记录的命令行选项。所以目前可能一些 CSS(或其他)黑客是唯一的方法。

标签: css google-chrome pdf printing google-chrome-headless


【解决方案1】:

你可以run headless chrome from Node环境。

然后您就可以将其他参数传递给printToPdf function,包括pageWidthpageHeight

【讨论】:

  • 谢谢迪米特里。我知道这个选项,但它会导致其他问题: 1. Chrome 实例只接受一个调试连接。我必须为我的服务的每个实例在多个端口上生成多个实例。不是很酷。 2. 与事件(onLoad 等)同步是额外的复杂层。基本上我需要编写一个运行一个 Chrome 实例的包装程序,该程序将抽象页面加载、打印等。也不那么酷。这就是为什么我想在每个作业中使用单个 Chrome 实例,完成后自动关闭,无需远程调试。更简单
【解决方案2】:

前段时间创建了一个补丁,可以启用页面大小配置https://codereview.chromium.org/2829973002/

它现在已经关闭并且在不稳定版本的chrome中可用,所以你可以按照你的建议使用它@page { size: A4 }

我测试过,它适用于我安装的不稳定版本 (Google Chrome 61.0.3141.7 dev)。不过,我不确定如何检查它何时在稳定版本中可用...

【讨论】:

  • 那行不通。我已经安装了 Chrome 61.0.3153.4 并在 css 中设置了@page { size: A4 }。这没什么区别。您是否能够通过这种方式获得不同尺寸的纸张?无论如何,您链接的更改与此问题并没有真正的联系。看这里:codereview.chromium.org/2829973002/patch/1/10010,使用 shell --print-to-pdf 选项时,参数被残酷地硬编码。它与@Dimitry Leonov 的回答更相关,因为它可以让您在使用调试 api 时进行控制。
  • 哦,奇怪,它似乎在我的机器上工作。这是我刚刚用无头镀铬制作的 2 代不同的产品。第一个是@page { size: A4; },第二个是A3。输出和你看到的imgur.com/QaQQQ8Rimgur.com/CYpMopU不一样。也就是说,红色部分的大小应该是210mm / 297mm,所以我不确定为什么侧面有额外的边距......
  • 关于我发给你的补丁链接,当我询问无头 chrome bugs.chromium.org/p/chromium/issues/detail?id=603559#c30 的页面大小配置时,Chromium 团队的某个人给我发了这个链接。所以我虽然这也与你有关,但不幸的是我不得不承认我真的无法理解这个补丁中发生了什么:/
  • 你是对的,输出可能不一样。案例是:有 3 种不同的大小:paperpagebody。您已更改page 的大小,而paperbody 保持不变。 Chrome 将更大的page 压缩到相同的paper 大小,因此您的body 在视觉上变得更小。它看起来类似于在较大的纸张尺寸上打印,但您可以检查 pdf 属性,您会发现它保持不变(至少在我的情况下)
  • 我不太了解这三种不同的尺寸。您似乎比我对 PDF 了解更多,所以我想我无法帮助您,抱歉:/ BTW 我向您展示的结果与您的预期有何不同?这是否意味着我需要以某种方式查看生成的 PDF 的元数据?
【解决方案3】:

注意:在通过 atomrc 的答案中的 cmets 之后,我考虑将其添加为更清晰的答案。

除非使用 devtools 协议,否则您现在无法更改页面大小。

这是a bug in headless Chrome@page size CSS 规则在无头模式下无法正确理解,as this user describes it well on the chromium bug tracker

Desktop Chrome 确实支持@page at-rules 的大小和边距,并且会根据 size 属性设置工作表尺寸。

Headless Chrome 似乎在某种程度上也解析了@page,但其行为与桌面版本不同:如果您指定@page {size},headless 似乎会改变页面框的尺寸(本质上,打印区域),而不是始终保持美国信函大小的工作表。但是,如果您指定 {size: Landscape},它会旋转工作表。

【讨论】:

    【解决方案4】:

    现在显然可以“几乎”精确控制页面大小,而无需使用调试界面。

    以下是使用 headless chrome 创建其内容尺寸几乎完全相同的 PDF 的方法。

    <head>
        <style>
          html, body {
            width:  fit-content;
            height: fit-content;
            margin:  0px;
            padding: 0px;
          }
         </style>
    
         <style id=page_style>
          @page { size: 100px 100px ; margin : 0px }
         </style>
    
    </head>
    

    这准备使 pdf 适合页面,但不正确,因为页面大小已设置为 100x100 的任意值。

    文档渲染完成后,使用以下方法在页面底部正确设置页面大小:

    <script>
    window.onload(fixpage);
    
    function fixpage() {
    
         renderBlock = document.getElementsByTagName("html")[0];
         renderBlockInfo = window.getComputedStyle(renderBlock)
    
         // fix chrome page bug
         fixHeight = parseInt(renderBlockInfo.height) + 1 + "px"   
    
         pageCss = `@page { size: \${renderBlockInfo.width} \${fixHeight} ; margin:0;}`
         document.getElementById("page_style").innerHTML = pageCss
    }
    </script>
    

    这种方法消除了页眉/页脚,并处理了像素转换为 pdf 的数字问题。

    还有一件事

    Chrome 目前在使用 CSS 时计算 div 的绝对高度存在错误

    line-height: normal; 
    

    这会使页面计算过短并导致生成额外的 pdf 页面。您可以使用以下方法解决此问题:

    line-height: unset; 
    

    贯穿您的 CSS。没有它,您将无法获得准确的高度!

    【讨论】:

      【解决方案5】:

      页面大小可以以英寸/毫米为单位设置。我还没有测试过像素大小。这是一组对我有用的 CSS 规则:

      @page {
        margin: 0;
        padding: 0;
        size: 5in 6.5in;
      }
      

      我的确切情况是渲染 svg-to-pdf,而不是 html;对于 svg,您可能还需要将 widthheight 属性添加到 &lt;svg&gt; 标签:

      <svg width="5in" height="6.5in" ...>
      

      就是这样!输出 PDF 不会有边距,并且会保留所需的大小 - 在我的情况下为 5"x6.5"。

      【讨论】:

      • 我只是将样式标签放入我的 HTML 的头部(没有 CData),以 mm 为单位设置大小,它就可以工作了。
      • 是的,对于 HTML 来说确实如此 - 只需在 中添加一个样式标签。我的情况是用于 svg 渲染,所以我需要 CDATA。我应该在回答中更清楚地说明。
      猜你喜欢
      • 1970-01-01
      • 2015-07-01
      • 1970-01-01
      • 2010-10-15
      • 2020-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-29
      相关资源
      最近更新 更多