go语言生成PDF

最近由于工作需要,将之前用phantomjs生成PDF报告的部分重构(phantomjs在数据量较大时候,占用太高的服务器资源),改用go代码直接生成,在GitHub上搜索相关第三方库, 关键词:pdf language:Go,按照star排序如图:

go语言书 rpc go语言编程pdf_go语言书 rpc

在各大网站上查找相关资料后,大致了解如下:

  1. jung-kurt/gofpdf 的star数量较多,但是更新频率较低,在我用的时候,最新的tag是v2.17.2,已经有将近两年没更新了,有很多open的issue没有关,担心不会再更新,所以当时没有考虑用这个。

另外,go语言中文网有一篇文章说这个包不支持中文,是的,那篇文章是2017年的,当时不支持,这个库2019年更新了,现在是支持的。

go语言书 rpc go语言编程pdf_初始化_02

  1. 排在第二的是gotenberg/gotenberg,这个库主要用于将其他类型的文件转化为PDF,以及合并PDF的,不符合我们的需求,暂不考虑。
  2. pdfcpu/pdfcpu 是一个用于合并PDF的命令行工具,也不符合需求,暂不考虑。
  3. signintech/gopdf 初步看着还是比较符合需求,再看一看其他的。
  4. unidoc/unipdf 是unioffice的一个PDF工具,他们还有个比较厉害的用于生成word的库,不过使用需要商业授权,源码也做了混淆,加上文档有限,不是太好用,先不考虑了。
    附unipdf部分源码截图:

最终,对比了多个第三方库之后,选用了signintech/gopdf

这个库的部分功能还有待完善,比如自动分页,自动换行等。大纲书签功能,之前只有最基本的跳转功能,而且跳转功能有些问题,会跳转到下一页,我提交了一次优化,并附带了demo,现在作者已经将我提交的那部分合入了。

代码示例:

package main
import (
	"log"
	"github.com/signintech/gopdf"
)

func main() {
	pdf := gopdf.GoPdf{}
	pdf.Start(gopdf.Config{ PageSize: *gopdf.PageSizeA4 })  
	pdf.AddPage()
	err := pdf.AddTTFFont("wts11", "../ttf/wts11.ttf")
	if err != nil {
		log.Print(err.Error())
		return
	}
	err = pdf.SetFont("wts11", "", 14)
	if err != nil {
		log.Print(err.Error())
		return
	}
	pdf.Cell(nil, "您好")
	pdf.WritePdf("hello.pdf")

}

先来说说这个库使用的大致流程(如上面代码块):

  1. 首先下载并在代码里引入这个包:import "github.com/signintech/gopdf"
  2. 初始化一个pdf对象:pdf := gopdf.GoPdf{}
  3. 初始化配置(页面尺寸):pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4});这里的PageSizeA4指的是用A4纸的尺寸,即宽210mm,高297mm;在分辨率为72px/inch的时候,宽高分为约为595px、842px,使用px更符合实际场景,比如UI给的设计稿一般都是像素单位;
  4. 添加一页画布:pdf.AddPage()
  5. 添加字体,可以从ttf文件直接读取,也可以使用字节流的字体数据:err := pdf.AddTTFFont("wts11", "../ttf/wts11.ttf"),可以在初始化的时候添加多个字体,以便后续在不同地方选用不同的字体;
  6. 设置字体:pdf.SetFont("wts11", "", 14),这里的wts11是上面设置的,如果上面设置的是abc,这里用的时候也是abc。这一步一定不要忘记,否则生成的时候回抛一个空指针异常;
  7. 绘制内容,可以是文字、线条、图片、图形、填充颜色等等,自由度极高。(但是文字不会自动换行…)
  8. 保存输出到pdf文件:pdf.WritePdf("hello.pdf")

相关代码示例和使用注意事项后续有空了再详细写写。

gopdf使用注意事项及常见问题