如何在无头 Chrome 中更改纸张尺寸 --print-to-pdf

Posted

技术标签:

【中文标题】如何在无头 Chrome 中更改纸张尺寸 --print-to-pdf【英文标题】:How can I change paper size in headless 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(或其他)黑客是唯一的方法。 【参考方案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   ...>

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

【讨论】:

我只是将样式标签放入我的 HTML 的头部(没有 CData),以 mm 为单位设置大小,它就可以工作了。 是的,对于 HTML 来说确实如此 - 只需在 中添加一个样式标签。我的情况是用于 svg 渲染,所以我需要 CDATA。我应该在回答中更清楚地说明。

以上是关于如何在无头 Chrome 中更改纸张尺寸 --print-to-pdf的主要内容,如果未能解决你的问题,请参考以下文章

EXCEL中纸张尺寸如何让设置自定义大小?

原TSC-342E PRO chrome两列打印配置

[紧急求助]mapx 如何打印任何尺寸纸张?

无头 Chrome 屏幕截图的最大高度为 16,384 像素?

如何获取所有纸张尺寸名称和相应的像素尺寸?

如何在 selenium 中使用无头 Chrome 启用 JavaScript