(2021年4月) Ruby on Rails 导出 PDF 时如何指定字体(用了 Docker)
在 Dockerfile 里用 ADD 指令就能解决问题

这篇文章写什么?
用 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

方法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" 写在这里,如果不这么写,一些字的渲染会和网页上不一致,比如"描述"里的 "述" 字会不同
}
这就完成了。
结果对比
更换字体前

更换字体后

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