11

我正在尝试使用 Chrome 的 Headless 功能将 html 转换为 pdf。但是,我根本没有得到输出。控制台也没有显示任何错误。我在我的 windows m/c 中运行以下命令。

chrome --headless --disable-gpu --print-to-pdf

我尝试了所有各种选择。什么都没有生成。我有 chrome 版本 60

4

7 回答 7

13

命令行 --print-to-pdf

默认情况下,--print-to-pdf尝试在用户目录中创建 PDF。默认情况下,该用户目录是存储实际 chrome 二进制文件的位置,这是您正在运行的版本的特定版本文件夹 - 例如,“C:\Program Files (x86)\Google\Chrome\Application\61.0. 3163.100"。而且,默认情况下... Chrome 不允许写入此文件夹。--enable-logging您可以通过添加到您的命令来观察它的尝试和失败。

所以不幸的是,默认情况下,此命令失败。*

您可以通过在参数中提供一个路径来解决这个问题,Chrome 可以在其中写入 - 比如

--print-to-pdf="C:\Users\Jane\test.pdf"

或者,您可以更改用户目录:

--user-data-dir="C:\Users\Jane"

您可能希望更改用户目录的一个原因是您希望 PDF 自动从网页接收其名称;Chrome 查看标题标签,然后将其转储为<title>My Page</title>=>My-Page.pdf

*我认为这种默认行为非常令人困惑,应该作为针对 Chrome 的错误提交。然而,显然 Chrome 团队的一部分人完全反对仅仅存在这个命令行选项,而是认为最好强迫每个人使用它来获得一个与 Puppeteer 一起使用的 node.js 构建,并彻底删除标志。

Windows 上命令行的限制

以这种方式调用 chrome 可以正常工作,例如在带有 Visual Studio 的 IIS Express 上的本地开发环境中,但它会在运行 IIS 的服务器上失败,即使在无头模式下,因为 IIS 用户没有被授予交互/桌面权限,并且chrome 获取此 PDF 的方式实际上需要交互式/桌面权限。提供这些权限有很复杂的方法,但是您在任何地方阅读有关如何以DON'T PROVIDE INTERACTIVE/DESKTOP PERMISSIONS开头的内容。此外,Chrome 有朝一日摆脱命令行的上述风险使得工作变得更加困难以使其工作成为一个不确定的提议。

chrome命令行的替代品

wkhtmltopdf

在幕后 Chrome 只是使用wkhtmltopdf。我还没有尝试过,但这很可能会完成工作。一个小风险是,在 Chrome 中生成 PDF 时,测试很明显:在 Chrome 中查看页面。如果您感到紧张,请打开打印预览。在 wkhtmltopdf 中,它实际上是 Chromium 的不同构建,这可能会产生渲染差异。也许。

另一种选择是领先于希望摆脱--print-to-pdf和使用浏览器开发 API(通过 Selenium)的团队。**

private static void pdfSeleniumImpl(string url, string pdfPath)
{
    var options = new OpenQA.Selenium.Chrome.ChromeOptions();
    options.AddArgument("headless");

    using (var chrome = new OpenQA.Selenium.Chrome.ChromeDriver(options))
    {
        chrome.Url = url;

        var printToPdfOpts = new Dictionary<string, object>();
        var resultDict = (Dictionary<string, object>)
            chrome.ExecuteChromeCommandWithResult(
                "Page.printToPDF", printToPdfOpts);
        dynamic result = new DDict(resultDict);
        string data = result.data;
        var pdfFile = Convert.FromBase64String(data);
        System.IO.File.WriteAllBytes(pdfPath, pdfFile);
    }
}

上面的 DDict 是我另一个答案中的 GracefulDynamicDictionary。

https://www.nuget.org/packages/GracefulDynamicDictionary/

https://github.com/b9chris/GracefulDynamicDictionary

https://stackoverflow.com/a/24192518/176877

理想情况下,这将是异步的,因为对 Selenium 的所有调用实际上都是网络命令,并且写入该文件可能会占用大量磁盘 IO。从 Chrome 返回的数据实际上也是一个 Stream。然而,不幸的是,Selenium 的传统使用库根本不使用异步,因此需要升级该库或为 .Net 确定一个可靠的异步 Selenium 库才能真正做到这一点。

https://github.com/puppeteer/puppeteer/blob/master/lib/Page.js#L1007

https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF

** Page.pdfchrome Dev API 命令也已被弃用,因此如果该特遣队得逞,命令行和 Dev API 都将不起作用。也就是说,看起来那些游说破坏它的人在 2 年前就放弃了。

于 2019-11-04T17:15:53.570 回答
8

这是有效的:

chrome --headless --disable-gpu --print-to-pdf=file1.pdf https://www.google.co.in/

在文件夹中创建文件:C:\Program Files (x86)\Google\Chrome\Application\61.0.3163.100.

于 2017-10-23T05:30:28.003 回答
3

我在 print-to-pdf 命令后丢失了“=”。

正确的命令是:

chrome --headless --disable-gpu --print-to-pdf="C:/temp/name.pdf" https://www.google.com/

现在它正在工作。

于 2017-09-06T12:59:35.943 回答
3

不要忘记以管理员权限打开您的终端/cmd :) 否则它根本不会保存文件。

于 2018-07-10T13:38:54.810 回答
2

通过 suraj 扩展了出色的简单答案,我在我的源路径中创建了一个小函数,因此它像 CLI 工具一样工作:

function webtopdf(){
    chromium-browser --headless --disable-gpu --print-to-pdf=$2 $1
}

这么快

webtopdf https://goo.com/some-article some-article.pdf

现在为我做这项工作

于 2018-05-29T12:15:51.443 回答
1

这在 Windows 中对我有用

启动 chrome --headless --disable-gpu --print-to-pdf=C:\Users\username\pdfs\chrome.pdf --no-margins https://www.google.com

于 2019-08-13T08:28:25.213 回答
-2

目前,这仅适用于 Linux 和 Mac OS。

于 2019-03-27T05:37:44.523 回答