【问题标题】:Headless Chrome to print pdf无头 Chrome 打印 pdf
【发布时间】:2018-02-14 21:16:46
【问题描述】:

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

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

我尝试了所有不同的选项。什么都没有生成。我有 chrome 版本 60

【问题讨论】:

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


    【解决方案1】:

    命令行 --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 团队的一部分人完全反对仅仅存在这个命令行选项,而是认为最好强迫每个人使用它来获得一个 node.js 构建与 Puppeteer 一起使用并彻底删除标志。

    Windows 命令行的限制

    以这种方式调用 chrome 可以正常工作,例如在带有 Visual Studio 的 IIS Express 上的本地开发环境中,但它会在运行 IIS 的服务器上失败,即使在无头模式下,因为没有为 IIS 用户提供交互式/桌面权限,而 chrome 获取此 PDF 的方式实际上需要交互/桌面权限。提供这些权限的方法很复杂,但是您在任何地方阅读到如何以不提供交互式/桌面权限开头。此外,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.pdf chrome Dev API 命令也已被弃用,因此如果该条件成功,命令行和 Dev API 都将不起作用。也就是说,看起来那些游说破坏它的人在 2 年前就放弃了。

    【讨论】:

    • 不明白为什么当前目录中的文件需要完整路径 - 例如:C:\Users\User\Documents\XstReader&gt;"C:\Program Files (x86)\Google\Chrome\Application\chrome" --headless --disable-gpu --print-to-pdf=C:\Users\User\Documents\XstReader\DemoEmail.pdf --no-margins "C:\Users\User\Documents\XstReader\Demo Email.html"
    • 因为 Chrome 会忽略当前目录,而是使用用户数据目录。
    • 这是一个很好的答案,应该得到至少 100 票。尤其是硒功能。谢谢 sm @ChrisMoschini
    • "幕后 Chrome 只使用 wkhtmltopdf。" - 需要引用。
    • 非常感谢 Selenium 提示!请注意,“headless”选项很重要,否则默认情况下,Chrome 中将禁用必要的扩展,从而导致“PrintToPDF is not implemented”错误。 (或者,它大概可以显式启用非无头模式,但我没有尝试过。)
    【解决方案2】:

    这是有效的:

    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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        在 print-to-pdf 命令之后我缺少“=”。

        正确的命令是:

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

        现在它正在工作。

        【讨论】:

        • 不要将答案用作 cmets
        • 这是正确答案,它需要将打印中文件的完整路径转换为 ​​pdf,或者截至 2019 年 5 月 27 日在 Windows 上不起作用
        【解决方案5】:

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

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

        这么快

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

        现在为我做这项工作

        【讨论】:

          【解决方案6】:

          这在 Windows 中对我有用

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

          【讨论】:

          • 您可以在 Powershell(和 GitBash)中使用 --print-to-pdf="$(pwd)\output.pdf" 在当前文件夹中打印。对我来说--no-margins 没有效果。
          【解决方案7】:

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

          【讨论】:

            猜你喜欢
            • 2018-12-24
            • 2018-02-15
            • 2021-01-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-08-20
            • 1970-01-01
            相关资源
            最近更新 更多