如何使用浏览器(Chrome/Firefox)的HTML/CSS/JS渲染引擎生成PDF?

26

有一些不错的项目可以从html/css/js文件生成pdf:

  1. http://wkhtmltopdf.org/(开源)
  2. https://code.google.com/p/flying-saucer/(开源)
  3. http://cssbox.sourceforge.net/(不一定直接生成pdf)
  4. http://phantomjs.org/(开源允许pdf输出)
  5. http://www.princexml.com/(商业软件,但是目前为止最好的)
  6. https://thepdfapi.com/可通过chrome修改从html生成pdf文件

我想编写程序以控制Chrome或Firefox浏览器(因为它们都是跨平台的),使它们加载网页、运行脚本并排版页面,然后生成一个用于打印的pdf文件。

但是如何开始以自动化的方式来控制浏览器,以便我可以执行类似以下命令:

render-to-pdf file-to-render.html out.pdf

我可以通过手动浏览页面并将其打印到pdf来轻松完成这项工作,我可以在pdf文件中获得准确的、100%规范兼容的渲染html/css/js页面。甚至可以通过浏览器中的配置选项省略pdf中的url头。但是,如何开始尝试自动化此过程呢?

我希望在服务器端自动化打开浏览器、导航到一个页面,并使用浏览器渲染的页面生成pdf。

我已经进行了很多研究,只是不知道如何提出正确的问题。我想以编程方式控制浏览器,可能类似于Selenium,但要将网页导出为PDF(因此使用浏览器的渲染功能来生成良好的PDF文件)。


2
你看过ChromeDriver了吗? - Chris Haas
2
你可能可以结合使用 Chromium 命令行参数 --kiosk --kiosk-printing,并在 prefs capability 中传递默认的 PDF 打印机来实现。我从未尝试过这样做,但这是我会开始尝试的地方。 - Chris Haas
1
我认为你需要进行一些真正的研究。在我看来,浏览器并不是为此而设计的,你还有许多障碍需要克服,这些障碍你还没有考虑到(例如可能运行页眉/页脚、保持内容在页面断点处的连续性、不同页面断点处的表头、字体处理/特殊字符处理和嵌入、理解浏览器尺寸是每英寸96个像素等等...我可以继续说下去,但这对你来说已经是一个开始了。 - Kevin Brown
2
@ChrisHaas,$ chrome --kiosk --kiosk-printing file.html,在html中我执行window.print();它正好做我想要的事情,只是仍然需要我按回车键保存文件...太遗憾了...不过还是谢谢。 - David Hofmann
1
我认为wkhtmltopdf是最接近你想要的。它是WebKit的一个分支版本,专门用于PDF生成。或者,如果你喜欢Prince,https://docraptor.com是一个商业SaaS API,由Prince引擎驱动。 - jamespaden
显示剩余4条评论
2个回答

6

我不是专家,但PhantomJS似乎是这项工作的合适工具。但我不确定它使用哪个无头浏览器(我猜测是Chrome/Chromium)。

var page = require('webpage').create();
page.open('http://github.com/', function() {
     var s = page.evaluate(function() {
         var body = document.body,
             html = document.documentElement;

        var height = Math.max( body.scrollHeight, body.offsetHeight, 
            html.clientHeight, html.scrollHeight, html.offsetHeight );
        var width = Math.max( body.scrollWidth, body.offsetWidth, 
            html.clientWidth, html.scrollWidth, html.offsetWidth );
        return {width: width, height: height}
    });

    console.log(JSON.stringify(s));

    // so it fit ins a single page
    page.paperSize = {
        width: "1980px",
        height: s.height + "px",
        margin: {
            top: '50px',
            left: '20px'
        }
    };

    page.render('github.pdf');
    phantom.exit();
});

希望这能有所帮助。

3
CSS可以在打印时进行页面大小调整。因此,在代码示例中设置纸张大小并没有帮助。此外,CSS打印还有分页功能。话虽如此,我注意到PhantomJS使用的是WebKit渲染引擎,而不是一个受支持的浏览器,而是一个WebKit的分支(对于这个任务来说还好)。但仍需要大量工作才能使其像princexml一样正常工作。我猜这就是它们不便宜的原因。 - David Hofmann

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接