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);
}
}
8条答案
按热度按时间6xfqseft1#
命令行--print-to-pdf
默认情况下,
--print-to-pdf
尝试在用户目录中创建PDF。默认情况下,该用户目录是实际chrome二进制文件的存储位置,这是您正在运行的版本的特定版本文件夹-例如,“C:\Program Files(x86)\Google\Chrome\Application\61.0.3163.100”。并且,默认情况下... Chrome不允许写入此文件夹。您可以通过将--enable-logging
添加到命令中来观察它的尝试和失败。因此,不幸的是,默认情况下,此命令失败。*
你可以通过在参数中提供一个路径来解决这个问题,Chrome可以这样写
或者,您可以更改用户目录:
您可能更喜欢更改用户目录的一个原因是,如果您希望PDF自动从网页接收其名称;Chrome查看标题标签,然后像
<title>My Page</title>
=〉My-Page.pdf
一样转储它Windows下命令行的限制
以这种方式调用chrome可以很好地工作,例如在使用Visual Studio的IIS Express上的本地开发环境中,但是即使在运行IIS的服务器上,即使在无头模式下,它也会失败,因为IIS用户没有被赋予交互式/桌面权限,而chrome抓取此PDF的方式实际上需要交互式/桌面权限。提供这些权限的方法很复杂。但是任何地方你读到如何开始 * 不提供交互/桌面权限 *.此外,上述风险的Chrome有一天摆脱命令行使工作更加困难,让它工作一个不确定的命题.
chrome命令行的替代方法
wkhtmltopdf
从源代码来看,Chrome团队要么使用了wkhtmltopdf,要么基于wkhtmltopdf。我还没有尝试过,但这可能会完成工作。一个小风险是,在Chrome中制作PDF时,测试是显而易见的:在Chrome浏览器中查看页面。如果您感到紧张,请打开打印预览。在wkhtmltopdf中,它实际上是Chromium的不同版本,这可能会产生渲染差异。也许。正如社区用户指出的那样,wkhtmltopdf由所有者于2023年1月2日存档。
Selenium
另一种选择是赶在那些希望摆脱
--print-to-pdf
的人之前,使用他们喜欢的浏览器开发API(通过Selenium)。上面的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库才能真正做到这一点。
任何基于Chrome的方法的限制
任何在服务器上使用Chrome的方法,包括Selenium,都必须处理Chrome的自动更新,以及需要更新的Selenium驱动程序以及构建的一部分。很少更新的代码如果没有科普策略,每3个月就会崩溃一次。
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年前就放弃了。mzsu5hc02#
这是工作:
在文件夹中创建文件:
C:\Program Files (x86)\Google\Chrome\Application\61.0.3163.100
.vfh0ocws3#
我在print-to-pdf命令后缺少“=”。
正确命令为:
现在它起作用了。
ccrfmcuu4#
扩展suraj的简单答案,我在我的源路径中创建了一个小函数,所以它像CLI工具一样工作:
所以很快
现在替我工作了
jm2pwxwz5#
别忘了用管理员权限打开你的终端/cmd:)否则它根本不会保存文件。
avwztpqn6#
这对我在windows工作
启动chrome --headless --disable-gpu --print-to-pdf= C:\Users\username\pdfs\chrome.pdf--no-margins https://www.google.com
gwbalxhn7#
对于Windows用户(以及其他使用MSEdge的用户),MSEdge提供了类似的功能-无头,此外版本III+具有“With Acrobat”渲染。
注意:Google Chromium使用不同的--switch!!
=new --no-pdf-header-footer
或=old --print-to-pdf-no-header
将headless更新为--headless=new和--headless=old注意,在版本112中,Edge不考虑headless=new。
较新--交换机位于https://peter.sh/experiments/chromium-command-line-switches/
目前MSEdge使用--headless命令,就像--headless=old一样,因此仍然使用旧的-header语法,
--headless --print-to-pdf-no-header
也不会写入页脚。没有必要设置配置文件,但您可以通过
应该没有必要使用任何GPU修补程序,这些都在Windows 5年前解决
因此,普通的日常命令可以是CWD是当前工作目录的任何路径
guz6ccqo8#
目前,这仅适用于Linux和Mac OS。