PhantomJS生成PDF中文及特殊字符乱码问题排查咨询
问题根本原因
- 你观察到的乱码特征(
"骆高" → "éªé«"、"TÜV" → "TÃV")是UTF-8编码字节被强制按ISO-8859-1(Latin-1)单字节编码解析的典型表现,和ASCII编码无关。 - 核心问题1:PhantomJS 1.9.8版本的stdin读取逻辑默认继承系统编码,不会自动识别传入的UTF-8格式参数。你在Node侧调用
child.stdin.write时指定了utf8编码,所有Node侧日志打印正常,但PhantomJS执行渲染的pdf_a4_portrait.js脚本读取stdin输入时,没有显式指定UTF-8编码,拿到的HTML字符串在渲染前就已经是乱码状态。这也是你之前加meta标签、设置phantom.outputEncoding都不生效的原因——phantom.outputEncoding仅控制PhantomJS输出日志的编码,完全不影响stdin读取、页面渲染的编码逻辑。 - 核心问题2:Galaxy部署用的是精简Linux容器镜像,默认没有预装中文字体和CJK兼容字体包,PhantomJS渲染PDF时找不到对应字符的字形映射,即使编码传递正确也可能出现乱码、方块字问题。
- 额外配置错误:你写入S3时使用
new Buffer(buffer, 'utf8')处理PDF文件是错误逻辑,fs.readFile拿到的PDF内容是二进制Buffer,强行指定utf8转码会破坏二进制文件结构,反而可能加剧内容异常。
可行修复方案
按优先级依次操作即可解决问题:
- 修复PhantomJS侧stdin读取编码
打开项目路径下的assets/packages/fta_phantomjs/scripts/pdf_a4_portrait.js脚本,找到读取stdin输入的代码段,显式指定编码为UTF-8,参考修改:
注意:PhantomJS 1.9.x版本的编码自动识别存在已知bug,必须显式设置编码,不能依赖默认逻辑。var system = require('system'); var input = ''; // 新增该行,强制stdin按UTF-8编码读取 system.stdin.setEncoding('utf8'); system.stdin.on('data', function(chunk) { input += chunk; }); system.stdin.on('end', function() { // 再解析JSON参数,此时拿到的html字段编码正常 var args = JSON.parse(input); // 后续保留原有页面渲染、PDF生成逻辑即可 }); - 补全Galaxy运行环境字体依赖
在项目构建流程中添加字体安装步骤,确保容器内有可用的中文字体:- 在项目根目录新建
galaxy-postinstall.sh脚本:
#!/bin/bash apt-get update -y apt-get install -y --no-install-recommends fonts-wqy-zenhei fonts-wqy-microhei fonts-noto-cjk fontconfig fc-cache -fv- 在项目
package.json中添加postinstall钩子,保证Galaxy部署时自动执行脚本:
"scripts": { "postinstall": "chmod +x ./galaxy-postinstall.sh && ./galaxy-postinstall.sh" } - 在项目根目录新建
- 清理无效配置、修正错误逻辑
- 删除S3上传时的多余编码指定,直接传读取到的二进制Buffer即可:
s3.putObject Bucket: "<Bucket>" Key: "<Key>" Body: buffer # 去掉new Buffer和utf8参数,直接传读出来的二进制内容 ContentType: 'application/pdf' - HTML模板里只保留一个
<meta charset="utf-8" />标签即可,重复添加的http-equiv meta标签属于冗余配置,不会提升兼容性,可以删掉。 child.stdin.setEncoding('utf8')、child.stdout.setEncoding('utf8')的配置可以保留,不影响功能。
- 删除S3上传时的多余编码指定,直接传读取到的二进制Buffer即可:
- 长期优化建议
PhantomJS 1.9.8是2014年发布的老旧版本,存在大量编码、渲染兼容bug,条件允许的话建议升级到PhantomJS 2.1.3版本,或者直接迁移到Puppeteer,对Unicode、中文字体的支持稳定性远高于老版本PhantomJS。
内容的提问来源于stack exchange,提问作者johanmetlef
相关产品推荐
相关产品推荐

