原文:www.smashingmagazine.com/2019/06/cre…javascript
译者:前端小智css
阿里云最近在作活动,低至2折,有兴趣能够看看:promotion.aliyun.com/ntms/yunpar…html
为了保证的可读性,本文采用意译而非直译。前端
在一些场景下,用户都要求一些须要的数据能以 pdf 的格式下载下来。如电子商务商店,常常须要一些报表数据来分析当月的销售状况。java
在本文中,将探讨如何从一个web应用程序中直接生成一个PDF。这不是一个生成 PDF 库列表,这里主要的目的是展现不一样生成 PDF 的方法。若是你有本身喜欢的工具或任何经验能够在评论中分享给咱们。react
首先考虑如何使用HTML和CSS生成PDF版本。ios
CSS确实有一个处理打印CSS的规范,就是 Paged Media module。所以,CSS自己就有打印材料的规格,咱们固然应该可以使用它?git
用户生成PDF的最简单方法是直接经过的浏览器,选择打印 PDF,将生成一个PDF。可悲的是,这个PDF一般并不彻底使人满意!首先,它会有页眉和页脚,当你从网页打印内容时,这些页眉和页脚会自动添加。固然若是你有一个样式表,它也会根据打印样式表进行格式化。github
用浏览器直接打印的一个问题是浏览器对片段规范(fragmentation )的支持不足。这可能意味着你的页面内容以不一样寻常的方式中断。这说明你可能没法防止内容的次优中断,如标题将做为页面上的最后一项保留,依此类推。web
此外,咱们没法控制页边距框中的内容,例如 将咱们选择的标题添加到每一个页面或页码编号,以显示页数。 这些内容是Paged Media规范的一部分,但还没有在任何浏览器中实现。
还有一些方法可使用浏览器渲染引擎将文档打印成PDF,而不须要在浏览器中使用打印的菜单,而且以页眉和页脚结束。在我以前的的推文时,最受欢迎的选项是wkhtmltopdf
,以及使用无头Chrome
和Puppeteer
打印。
接受HTML文件或多个文件,以及样式表,并将其转换为PDF。它经过使用WebKit渲染引擎来实现这一点。
所以,从本质上讲,这个工具与与浏览器打印效果是同样的,可是,不会获得自动添加的页眉和页脚。从乐观上讲,若是你有一个可用于内容的打印样式表,那么可使用这个工具很好地打印PDF,所以一个简单的布局可能打印得更好。
然而,不幸的是,因为不支持分页媒体规范和片断(fragmentation)属性,仍然会遇到与直接从web浏览器打印相同的问题,由于仍然使用的是浏览器渲染引擎进行打印。
能够将一些标志传递到wkhtmltopdf中,以便使用分页媒体规范在缺省状况下添加一些缺失的特性。然而,这确实须要一些额外的工做,除了写好的 HTML 和CSS。
另外一种是使用无头的谷歌浏览器来打印 PDF。
然而,再次受到浏览器对 Paged Media 和 fragmentation 支持的限制。有一些选项能够传递到page.pdf()
函数中。与wkhtmltopdf同样,若是有浏览器支持,添加了一些CSS 提供的功能。
极可能这些解决方案中的一个能够知足你的全部需求,可是,若是发现你正在进行某种程度的任务,极可能已经达到了当前浏览器渲染引擎的极限,这就须要寻找更好的解决方案。
尝试使用JavaScript 实现Paged Media规范 - 其实是建立了 Paged Media Polyfill。 也能够在使用 Puppeteer 提供对 Paged Media支持。 看看 paged.js和 Vivliostyle。
若是你想继续使用 HTML 和 CSS 解决方案,那么你须要查看用于从 HTML 和 CSS 打印的用户代理(UA),其中包含用于从文件生成 PDF 的 API。 这些用户代理实现了Paged Media规范,而且对 CSS Fragmentation属性有了更好的支持;,这样能够更好地控制输出: 主要选择包括:
打印UA将像web浏览器同样使用CSS格式化文档。与浏览器支持CSS同样,须要查看这些UA的的文档,以了解它们支持什么。例如,Prince
在编写本文时支持Flexbox,但不支持CSS网格布局。当将页面发送到正在使用的工具时,一般会使用一个用于打印的特定样式表。与常规打印样式表同样,我在站点上使用的CSS并不都适合PDF版本。
为这些工具建立样式表与建立常规打印样式表很是类似,可能使用不一样的字体大小或颜色来决定显示或隐藏什么。而后,能够利用**分页媒体规范( Paged Media specification)**中的功能,添加脚注、页码等。
就从web应用程序使用这些工具而言,须要在服务器上安装它们。这些工具的主要问题是它们很昂贵。也就是说,考虑到你能够轻松地使用它们生成打印文档,它们可能会在节省的开发人员时间中获得很好的回报。
能够经过API(按文档付费)经过DocRaptor服务使用Prince。对于许多应用程序来讲,这无疑是一个很好的起点,由于它看起来彷佛可使你本身的主机变得更加经济有效,而切换的开发成本将是最小的。
一个免费的替代方案是WeasyPrint,它不像上面的工具那么全面,但颇有可能已经知足你的需求。它没有彻底实现全部分页媒体规范,可是,它实现的比浏览器引擎更多。固然,你能够试试!
声称支持从HTML和CSS转换的其余工具包括PDFCrowd,它大胆声称支持HTML5,CSS3和JavaScript。 可是,我没法找到关于支持的确切内容的任何细节,以及是否有任何分布媒体规范。
还有许多其余的解决方案,它们再也不使用HTML和CSS,而是要求你为工具建立特定的输出。下面是对应的工具:
除了基于javascript的方法(它要求打印内容建立彻底不一样的表示形式)以外,这些解决方案的优势在于它们是可互换的。若是你的解决方案基于调用命令行工具,并将该工具传递给你的HTML、CSS,可能还传递一些JavaScript,那么在工具之间切换是至关简单的。
为了支持分布媒体和fragmentation,Prince,Antenna House 和 PDFReactor能够做为首选。 做为商业产品,他们也获得了支持。
可是,在许多状况下,免费工具也很适合。 若是你的的需求很是简单,那么wkhtmltopdf,或者基本的无头Chrome 和 Puppeteer就能够解决问题。
可是,若是你发现打印的结果不是本身想要的,请注意这多是浏览器打印的限制,而不是你作错了什么。若是你想要更多的页面媒体支持,但又没法得到商业产品,也许能够看看WeasyPrint。
但愿这是一个有用的工具总结,可用帮你的web应用程序建立pdf。
干货系列文章汇总以下,以为不错点个Star,欢迎 加群 互相学习。
我是小智,公众号「大迁世界」做者,对前端技术保持学习爱好者。我会常常分享本身所学所看的干货,在进阶的路上,共勉!
关注公众号,后台回复福利,便可看到福利,你懂的。