客户手机打开 PDF 中文全是方块,自己电脑却正常,是字体没嵌进去还是阅读器不认?
结论:PDF 在自己电脑上中文正常、客户手机打开全是方块,常见原因并非服务器没装字体,而是字体文件、字体族名匹配、字形嵌入这三段里有一段没接上。按 2026 年常见交付经验,先别重复装字体,用「文件—注册—匹配—嵌入」四层顺序核对,多数能在半小时到半天内定位到具体一层。
一、装了字体不等于 PDF 里嵌了字体
服务端生成 PDF 时,字体至少分三段:字体文件在运行环境里、渲染引擎能按模板写的 family 名找到它、生成时把用到的字形子集嵌进 PDF。把 ttf/otf 拷进 /usr/share/fonts,只解决第一段。开发机打开正常、客户打开出方块,常见就是本地字体兜住了缺字,而导出文件里没嵌入。
- 文件在,但字体缓存没刷新,fc-list 列不出 family,引擎当它不存在;
- 文件名像某个中文字体,内部 family 却是另一种写法,模板里的「宋体」「黑体」匹配不上;
- 名字匹配了,但只嵌入子集,动态插入的生僻字、全角标点不在子集里;
- 宿主机装了,容器镜像没装,换机器或重新发版又复发。
二、四层定位:从文件查到嵌入结果
PDF 生成是单向链路:文件→系统注册→引擎匹配→嵌入输出。从成品反推容易猜错,按固定顺序核对更快。
- 查文件:进运行环境(容器化部署进容器)确认目标字体文件存在,记下路径;
- 查注册:执行 fc-list,能列出对应 family 才算系统认识;列不出先刷新缓存,再查路径和权限;
- 查匹配:模板里写 fc-list 输出的确切 family 名;引擎支持直接指定字体文件路径时,通常比写名字更稳;
- 查嵌入:用 pdffonts 或阅读器文档属性看字体是否标记为已嵌入;前三层通过、这层没通过,说明生成参数把嵌入关了。
验收口径建议写成:在未额外安装中文字体的干净电脑和手机上打开导出的 PDF,中文、标点、符号显示正常。不要只写「我这边打开没问题」。
三、HTML 转 PDF 和模板直绘,差别不只在开发量
两条路对系统字体目录的依赖不同,后续换环境是否复发也不同。下面给常见经验区间,具体随模板复杂度和团队熟悉度浮动。
- HTML 转 PDF:现有页面样式可复用,首版常见 0.5~2 人日;依赖运行环境字体目录,镜像体积常见增加几十到一两百 MB,分页、跨页表头、页脚页码要反复调。
- 模板直绘:分页、表格、页码、水印更可控,字体以文件流加载,不依赖系统字体目录;代价是排版要写代码,常见 3~10 人日,改样式就是改代码。
- 折中:固定版式的合同、发票、对账单用模板直绘,页数不定的说明文档走 HTML 转 PDF,两套共用同一份字体文件。
判断上,版式强依赖设计稿、页数不定、要复刻网页观感,偏向前者;版式固定、字段整齐、批量出几千份,偏向后者。偶尔导出一两页确认单,硬上模板直绘容易变成过度设计。
四、交付现场:内网精简镜像和两种字体
遇到过客户内网服务器用精简镜像,没有外网也装不了包管理器,甲方只给了一份字体授权文件,而合同模板标题和正文各用一种字体。第一版把拿到的字体拷进镜像,结果标题出字、正文仍是方块;把正文 family 临时统一到可用字体后中文全出,但客户要求标题保持原字体,最后把两个字体文件一起打进镜像并逐项核对模板字体名,来回返工两轮,整体周期比原计划多出两三天。这类返工在经验区间里不算少见,常见区间是半天到三天,取决于字体授权和模板字体种类。
验收前可提前核对:只在宿主机装字体、容器没装;只测整段中文,没测生僻字、全角标点、货币符号、书名号;字体版权没确认就打包;嵌入完整字体让几百页文档从几 MB 涨到几十 MB;只在桌面阅读器看过,没在手机自带阅读器打开。
五、适用与不适用边界
这套顺序适用于服务端生成含中文 PDF 的合同、发票、报表、证书、对账单,也适用于测试、预发、生产多套环境字体不一致导致的缺字。
- 适合:服务端批量生成、需要归档、要直接发给外部客户打开即看;
- 适合:容器化部署,换机器后复发缺字;
- 不必上:内容只有数字和英文,系统自带字体够用;
- 不适用:PDF 在客户端生成(浏览器打印、前端库导出),排查点在用户机器和浏览器;
- 不适用:客户要求 PDF 内文字可编辑且保留原字体,这涉及字体授权与嵌入策略,要单独约定。
边界上要分清:把字体打进镜像解决的是显示,解决不了授权。有版权的商用字体要按甲方书面授权范围使用,拿不到书面确认时,优先换可商用字体再谈版式还原;2026 年的项目合规审查里,这一点常被提前问到。
下次遇到 PDF 中文方块,先按文件、注册、匹配、嵌入四层走一遍,多数问题能定位到具体一层。版式固定、批量生成量大时,项目初期就选不依赖系统字体目录的方案,能省掉换环境的重复排查;字体授权仍以甲方书面确认范围为准。
常见问题
客户手机打开是方块、自己电脑正常,先查嵌入还是先查字体名?
先查嵌入。用 pdffonts 或文档属性看字体是否已嵌入;未嵌入再回到模板 family 名核对。自己电脑正常,常是本机字体兜住了缺字。
fc-list 能看到字体,模板里写「宋体」还是方块,名字怎么对?
用 fc-list 输出的确切 family 名替换口语名,并在导出进程所在的同一容器里执行核对;名字差一个空格或中英文括号都可能匹配不上。
容器镜像里只放一个中文字体文件够不够?
看模板用几种 family。经验区间是放 1~2 个业务真正用到的字体;标题和正文用不同 family 时只放一个,常见结果是标题出字、正文方块。
客户给的商用字体能直接打进镜像发给外部吗?
不能只看「客户给的」。要确认书面授权覆盖服务器嵌入和对外分发;覆盖不到就换可商用字体,别等交付合规审查再返工。
-
定时任务两台机器都在跑,月底对账单出了两份,分布式锁到底挡得住哪一段?
日期:2026年11月2日 阅读:19
-
客户门户用 iframe 嵌了我们系统,用户登录完又被弹回登录页,先查 Cookie 还是先查会话?
日期:2026年11月1日 阅读:90
-
把连接池上限从 20 调到 50,早高峰超时反而更多了,连接到底被谁占着?
日期:2026年10月31日 阅读:29
-
用户扫码后手机点了确认,PC 登录页还停在转圈,先查轮询间隔还是先查二维码状态?
日期:2026年10月30日 阅读:39
-
服务从两台扩到六台,订单号偶尔撞车,雪花 ID 的机器号能手写配置吗?
日期:2026年10月29日 阅读:76




