使用JavaScript在浏览器中生成PDF文档

开发/前端 · 阅读 2016 · 点赞 0

前提背景

在计量领域中,计量检定是一种重要形式,主要用于评定计量器具的计量性能,确定其量值是否准确一致,实现手段包括计量检验、出具检定证书和加封盖印等。

在检定证书这一环节,存在一个难点,就是无法在线预览以及智能生成。

1、证书管理不能满足用户精准打印、特殊字符或多页打印的需求。因为在计量行业中,精密仪器较多,往往会存在一些特殊字符的应用或者会使用某些较为复杂的测量单位。

2、系统不支持批量证书更新以及批量打印等功能,在常见的场景中,出具证书是需要进行批量导出的过程。

3、无法满足实时打印预览或者pdfPDF预览,这样只直至打印前都无法确定打印的格式、范围等是否符合需求。

在这篇分享中,我们将帮助大家着重解决两个问题:

1、在浏览器中生成PDF文件;

2、解决中文以及特殊字符导出PDF乱码的问题。

在浏览器中生成PDF文件。前端生成PDF文件纯依赖于客户端的浏览器资源,对于不同的终端,导出PDF的难度会比服务端有所增加。市面上主流的浏览器有三四家,例如Chrome、Safari、FireFox等,每个浏览器对于文字内容、CSS属性处理都不一致,有可能某些配置在某个浏览器上可行,换了一个浏览器之后就有可能天差地别。另外,对于原生的PDF文件来说,仅包含英文字体,不包含任何中文字体,因此当导出的内容中含有中文字体编码时,就会显示乱码,所以通常情况下,我们都需要为PDF进行字体注册操作。

前端常见导出PDF方法

目前常用的前端生成PDF文件的方法大致有以下几种。

1、HTML2Canvas的方法将HTML 转换成图片后,在将图转PDF文件。这种方法比较适合单一页面。

2、jsPDF 直接H5转成PDF。

除了上述的方案之后,使用SpreadJS直接在线设计布局,并且可以直接生成PDF文件。 带来的好处是什么呢?可视化的操作、代码量少并且可以适配不同的浏览器环境。当然也会有一定的缺点。,对于字体较多的文件,需要注册不同的字体,字体文件越大,占用的带宽就越大。另外,当文件比较大的时候,有可能会存在性能问题,不过这个也几乎是前端导出PDF文件的一个瓶颈。那么较为理想的方案便是可以在前端(SpreadJS)设计、展示,最后交由后端来单独导出或者批量导出。

在浏览器中生成PDF文件

介绍了那么多,我们还是回到本篇文章的主题,如何通过前端来生成PDF文件。需要用到SpreadJS以及导出PDF相关的功能,首先需要在页面上引入相关的资源。

然后创建一个用于承载表格实例的DOM。

初始化表格控件并加载已设计好的表单,或者也可以通过setValue的接口实现简单的赋值操作。

想要表单按照指定的要求导出,可以通过代码设置打印相关的配置,也可以用设计器来进行设计。下面是配置打印信息相关的代码。

最后,通过调用savePDF方法,将工作簿对象转为blob,我们可以通过window.open来进行pdf的预览或者通过一些保存文件的插件直接将这个blob保存为PDF文件。

这是open之后的效果,我们可以直接通过浏览器导出PDF文件或者是调用浏览器的打印接口实现打印。

解决中文以及特殊字符导出PDF乱码

正如前面所说的,在国内,使用中文的报告是一件再常见不过的事,在计量检测等相关场景,特殊字符的使用也较多。在没注册对应的字体之前,导出的中文字体和特殊字体都显示的是乱码。因此,还需要处理导出中文以及特殊字符PDF乱码的问题。

前面提到了注册字体,那我们的字体应该怎么来?要什么格式的字体呢?首先,先确认我们的表单需要用到哪些字体,然后去找对应字体的ttf文件(电脑上或者是一些字体网站上都有,需注意版权问题)。找到之后将其转为base64格式的文件。具体如何转,可以找一些在线的文件转换器,不过在线的有可能会因为字体文件太大而崩溃,或者有能力的大佬可以自己写一个转换的工具。然后通过下面的方式去把我们的字体文件存储为一个js文件放到我们的项目中。

初始化表单这些就和上面的操作基本一致了,下面就是关键的注册字体步骤了。我们定义了一个font对象,里面只定义了常规(normal)的字体,里面的simkai.ttf就是我们上面的创建的字体文件。

还有一点需要注意的是,虽然注册了字体,但是要设置对应的中文字体。或者换过来说,你需要在表单上设置什么字体,就去注册对应的字体。

那我们再来看看特殊字符,注册字体与中文字体的步骤是一致的,特殊在于为了想要在页面上显示特殊字符,我们需要通过css的font-face来指定一个font-family。例如创建了一个叫sunway-font的特殊字体,想要在页面上显示。

最后就是通过savePDF方法导出PDF文件,可以看到PDF的中文和特殊字符都可以正常显示。