(2021年4月) Ruby on Rails 导出 PDF 时如何指定字体(用了 Docker)

这篇文章写什么?

用 Ruby on Rails 实现 PDF 导出功能时,如何设置 PDF 里的字体。

这篇文章对谁有用?有什么用?

对谁有用?Rails 开发者
有什么用?学会怎么在 Dockerfile 里引入字体

正文

现有的问题

PDF 里中文字体太丑了。如下图:

现有的做法

Dockerfile 里用的是这个镜像

FROM ruby:2.7.1-alpine3.12

它默认是没有中文字体的。

Dockerfile 里还有一句

# This font is required for Chinese characters to be rendered correctly in PDFs
RUN apk add wqy-zenhei --update-cache --repository http://mirrors.ustc.edu.cn/alpine/edge/testing/ --allow-untrusted

这是之前的外国同事写的(所以上面有一句英文注释)
这个 "wqy-zenhei" 是 "文泉驿正黑体"

如何解决

假设我们想换成"苹方"字体(举个例子)

第一步

我们复制这个 PingFang.ttc 文件。

问题来了,怎么让把这个字体文件放进镜像?

看下图,根据 Alpine 的文档,字体应该在 /use/share/fonts

https://wiki.alpinelinux.org/wiki/Fonts

方法1:把字体文件放进代码目录

把这个 PingFang.ttc 直接放进代码目录。
然后 Dockerfile 里写

COPY ./fonts/PingFang.ttc /usr/share/fonts 

这样有一个大问题,就是 git 里多了一个 77MB 的文件。
并不是所有的同事都开启了全局翻墙,所以有同事说 git pull 的时候非常慢。
所以这种方法不好。

方法2:把字体文件放在可以 URL 访问的地方

我这里直接放入 AWS S3,
当然你也可以放进阿里云 OSS,腾讯云 COS,七牛之类的地方,能访问就行。

然后 Dockerfile 里这样写

ADD https://[隐藏].s3.cn-north-1.amazonaws.com.cn/PingFang.ttc /usr/share/fonts

注意这里只是示例,所以 URL 删去了一部分。意思表达到就行了。

Docker 文档如何解释这条 ADD 命令?

https://docs.docker.com/engine/reference/builder/#add
If <src> is a URL and <dest> does not end with a trailing slash, then a file is downloaded from the URL and copied to <dest>.
也就是说这条 ADD 命令,会从 URL 把文件下载下来,然后放到你指定的文件夹。

最后

app/assets/stylesheets/pdf.scss 写上

body {
  font-family: "PingFang SC", "Avenir", Helvetica, Arial, sans-serif;
  // 把 "PingFang SC" 写在这里,如果不这么写,一些字的渲染会和网页上不一致,比如"描述"里的 "述" 字会不同
}

这就完成了。

结果对比

更换字体前

更换字体后

总结

  1. 选择你想要的字体(比如上面用的是"苹方")
  2. 如果是 macOS,去"字体册"里把字体文件找出来(比如上面是 "PingFang.ttc")
  3. 把 PingFang.ttc 存到 URL 可公开访问的地方(比如 AWS S3)
  4. 在 Dockerfile 里写 ADD <URL> <目标文件夹地址>
  5. 在 CSS 里写上要用这个字体
  6. 完成