Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Web应用程序如何创建 PDF #76

Open
husky-dot opened this issue Jul 15, 2019 · 0 comments
Open

Web应用程序如何创建 PDF #76

husky-dot opened this issue Jul 15, 2019 · 0 comments

Comments

@husky-dot
Copy link
Owner

原文:https://www.smashingmagazine.com/2019/06/create-pdf-web-application/

译者:前端小智

为了保证的可读性,本文采用意译而非直译。

想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!

在一些场景下,用户都要求一些需要的数据能以 pdf 的格式下载下来。如电子商务商店,经常需要一些报表数据来分析当月的销售情况。

在本文中,将探讨如何从一个web应用程序中直接生成一个PDF。这不是一个生成 PDF 库列表,这里主要的目的是展示不同生成 PDF 的方法。如果你有自己喜欢的工具或任何经验可以在评论中分享给我们。

从HTML和CSS开始

首先考虑如何使用HTML和CSS生成PDF版本。

CSS确实有一个处理打印CSS的规范,就是 Paged Media module。因此,CSS本身就有打印材料的规格,我们当然应该能够使用它?

用户生成PDF的最简单方法是直接通过的浏览器,选择打印 PDF,将生成一个PDF。可悲的是,这个PDF通常并不完全令人满意!首先,它会有页眉和页脚,当你从网页打印内容时,这些页眉和页脚会自动添加。当然如果你有一个样式表,它也会根据打印样式表进行格式化。

用浏览器直接打印的一个问题是浏览器对片断规范(fragmentation )的支持不足。这可能意味着你的页面内容以不同寻常的方式中断。这说明你可能无法防止内容的次优中断,如标题将作为页面上的最后一项保留,依此类推。

此外,我们无法控制页边距框中的内容,例如 将我们选择的标题添加到每个页面或页码编号,以显示页数。 这些内容是Paged Media规范的一部分,但尚未在任何浏览器中实现。

使用浏览器渲染引擎打印

还有一些方法可以使用浏览器渲染引擎将文档打印成PDF,而不需要在浏览器中使用打印的菜单,并且以页眉和页脚结束。在我之前的的推文时,最受欢迎的选项是wkhtmltopdf,以及使用无头ChromePuppeteer打印。

WKHTMLTOPDF

wkhtmltopdf

接受HTML文件或多个文件,以及样式表,并将其转换为PDF。它通过使用WebKit渲染引擎来实现这一点。

因此,从本质上讲,这个工具与与浏览器打印效果是一样的,但是,不会得到自动添加的页眉和页脚。从乐观上讲,如果你有一个可用于内容的打印样式表,那么可以使用这个工具很好地打印PDF,因此一个简单的布局可能打印得更好。

然而,不幸的是,由于不支持分页媒体规范和片段(fragmentation)属性,仍然会遇到与直接从web浏览器打印相同的问题,因为仍然使用的是浏览器渲染引擎进行打印。

可以将一些标志传递到wkhtmltopdf中,以便使用分页媒体规范在缺省情况下添加一些缺失的特性。然而,这确实需要一些额外的工作,除了写好的 HTML 和CSS。

无头 Chrome

另一种是使用无头的谷歌浏览器来打印 PDF。

然而,再次受到浏览器对 Paged Media 和 fragmentation 支持的限制。有一些选项可以传递到page.pdf()函数中。与wkhtmltopdf一样,如果有浏览器支持,添加了一些CSS 提供的功能。

很可能这些解决方案中的一个可以满足你的所有需求,但是,如果发现你正在进行某种程度的任务,很可能已经达到了当前浏览器渲染引擎的极限,这就需要寻找更好的解决方案。

使用 JavaScript 来实现 Paged Media规范

尝试使用JavaScript 实现Paged Media规范 - 实际上是创建了 Paged Media Polyfill。 也可以在使用 Puppeteer 提供对 Paged Media支持。 看看 paged.jsVivliostyle

使用打印用户代理

如果你想继续使用 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

还有许多其他的解决方案,它们不再使用HTML和CSS,而是要求你为工具创建特定的输出。下面是对应的工具:

推荐

除了基于javascript的方法(它要求打印内容创建完全不同的表示形式)之外,这些解决方案的优点在于它们是可互换的。如果你的解决方案基于调用命令行工具,并将该工具传递给你的HTML、CSS,可能还传递一些JavaScript,那么在工具之间切换是相当简单的。

为了支持分布媒体和fragmentation,Prince,Antenna House 和 PDFReactor可以作为首选。 作为商业产品,他们也得到了支持。

但是,在许多情况下,免费工具也很适合。 如果你的的需求非常简单,那么wkhtmltopdf,或者基本的无头ChromePuppeteer就可以解决问题。

但是,如果你发现打印的结果不是自己想要的,请注意这可能是浏览器打印的限制,而不是你做错了什么。如果你想要更多的页面媒体支持,但又无法获得商业产品,也许可以看看WeasyPrint

希望这是一个有用的工具总结,可用帮你的web应用程序创建pdf。

工具

交流

干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。

https://github.com/qq449245884/xiaozhi

我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!

关注公众号,后台回复福利,即可看到福利,你懂的。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant