Aspose.Words 转 PDF 中文乱码问题完整解决方案
本文详细介绍在使用 Aspose.Words 将 Word 文档转换为 PDF 时出现中文乱码的原因分析和解决方案,涵盖 Windows/Linux/Docker 全平台场景。
一、问题描述
1.1 现象
// 使用 Aspose.Words 转换 Word 到 PDF
Document doc = new Document("input.docx");
doc.save("output.pdf", SaveFormat.PDF);
Windows 环境: 转换正常,中文完美显示 ✅
Linux/CentOS 环境: 转换后 PDF 中的中文字符显示为乱码(方块、问号或空白) ❌
Docker 环境: 同样出现中文乱码 ❌
1.2 乱码表现形式
| 表现 | 截图示例 | 原因 |
|---|---|---|
所有中文显示为 □□□ 方块 | 文字被替代为系统缺失字体的占位符 | 完全缺失中文字体 |
中文显示为 ???? 问号 | 文本编码异常 | 字体回退失败 |
| 中文完全不显示(空白) | 被渲染引擎跳过 | 字体路径无效 |
| 部分中文正常,部分乱码 | 字体中有部分字符缺失 | 字体集不完整 |
二、问题原因
2.1 根本原因
Linux 服务器缺少对应的中文字库。
| 环境 | 是否预装中文字体 | 说明 |
|---|---|---|
| Windows | ✅ 是 | 系统自带 宋体、微软雅黑、黑体等 |
| macOS | ✅ 是 | 系统自带 苹方、华文细黑等 |
| Linux(最小安装) | ❌ 否 | 默认不包含中文字体 |
| Docker(Alpine) | ❌ 否 | 基础镜像仅包含极少字体 |
| Docker(CentOS/Ubuntu) | ⚠️ 部分 | 需要安装 fontconfig + 中文字体包 |
2.2 Aspose.Words 字体解析机制
Word 文档(DOCX)
↓
Aspose.Words 读取内容 + 字体引用
↓
查找系统字体(按优先级搜索)
│
├─→ Windows: C:\Windows\Fonts\ ✅ 找到中文字体
├─→ Linux: /usr/share/fonts/ ❌ 可能没有中文字体
├─→ Docker: 依赖镜像的字体包 ❌ 通常没有中文字体
│
↓ 字体未找到
Aspose.Words 使用默认回退字体
↓
回退字体(通常为西方字体)不含中文
↓
PDF 输出中文乱码
2.3 Aspose.Words 字体的回退顺序
// Aspose.Words 查找字体的顺序:
// 1. 文档中指定的字体名称(如果系统中有)
// 2. FontSettings.DefaultFontName(如果设置了)
// 3. 系统默认的 sans-serif 字体
// 4. 最接近的可用字体
// 在 Linux 上,回退链最终指向无中文字体的西方字体
// 导致中文全部变为方块
三、解决方案一:环境级——安装字体
3.1 从 Windows 复制字体到 Linux
步骤 1:准备字体文件
在 Windows 机器上,打开文件夹:
C:\Windows\Fonts
将需要的字体文件(.ttf / .ttc)复制出来。必选的中文字体:
| 字体文件 | 字体名称 | 说明 |
|---|---|---|
simsun.ttc | 宋体(SimSun) | 最常见的衬线中文 |
msyh.ttf / msyhbd.ttf | 微软雅黑 / 微软雅黑加粗 | 最常用的无衬线中文 |
simhei.ttf | 黑体(SimHei) | 标题用粗体 |
simfang.ttf | 仿宋(FangSong) | 公文用 |
simkai.ttf | 楷体(KaiTi) | 手写风格 |
SIMLI.TTF | 隶书(LiSu) | |
STXIHEI.TTF | 华文细黑 | |
msmincho.ttc | 明朝体 | 日文支持 |
简便做法:直接复制整个 Fonts 文件夹
# Windows 中压缩 C:\Windows\Fonts 文件夹
# 上传到 Linux 服务器
步骤 2:上传到 Linux
# 创建字体目录
mkdir -p /usr/share/fonts/chinese
# 上传字体文件(通过 scp 或 ftp)
scp -r /local/path/fonts/*.ttf root@server:/usr/share/fonts/chinese/
scp -r /local/path/fonts/*.ttc root@server:/usr/share/fonts/chinese/
# 或者使用 rz 命令
# rz # 选择字体文件上传
步骤 3:安装字体工具
# CentOS / RHEL
yum install -y mkfontscale fontconfig
# Ubuntu / Debian
apt-get update
apt-get install -y fontconfig ttf-dejavu
# Alpine(Docker)
apk add --no-cache fontconfig ttf-dejavu
步骤 4:生成字体缓存
# 进入字体目录
cd /usr/share/fonts/chinese
# 生成字体索引(CentOS 执行以下两条)
mkfontscale
mkfontdir
# 清空字体缓存
fc-cache -fv
步骤 5:使字体生效
# 重启应用,或执行:
source /etc/profile
# 如果服务已运行,需要重启 Java 进程
# 验证字体是否安装成功
fc-list :lang=zh
# 输出应类似:
# 宋体,SimSun:style=Regular
# 微软雅黑,Microsoft YaHei:style=Normal
# 黑体,SimHei:style=Regular
3.2 使用 yum/apt 安装中文字体包
# CentOS / RHEL 使用 epel 源
yum install -y epel-release
yum install -y cjkuni-uming-fonts # 宋体替代
yum install -y cjkuni-ukai-fonts # 楷体替代
yum install -y google-noto-cjk-fonts # Google Noto 中文字体
# Ubuntu / Debian
apt-get install -y fonts-wqy-microhei # 文泉驿微米黑
apt-get install -y fonts-wqy-zenhei # 文泉驿正黑
apt-get install -y fonts-noto-cjk # Google Noto CJK
3.3 查看 Linux 当前字体
# 查看所有字体
fc-list
# 查看所有中文字体
fc-list :lang=zh
# 查看字体文件路径
fc-list :lang=zh | head -5
# 输出示例:
# /usr/share/fonts/chinese/msyh.ttf: Microsoft YaHei:style=Normal
# /usr/share/fonts/chinese/simsun.ttc: SimSun:style=Regular
3.4 设置字体权限
# 如果字体安装后仍不生效,检查文件权限
chmod -R 755 /usr/share/fonts/chinese/
# 或者更严格的权限
chmod 644 /usr/share/fonts/chinese/*
chmod 755 /usr/share/fonts/chinese/
# 重新生成缓存
fc-cache -fv
四、解决方案二:代码级——Aspose 字体配置
4.1 设置默认字体
import com.aspose.words.*;
/**
* Aspose.Words 字体配置工具类
*/
public class AsposeFontUtil {
/**
* 设置默认字体为宋体(简单但有效)
*/
public static void setDefaultFont() {
FontSettings fontSettings = new FontSettings();
// 设置默认回退字体为宋体(必须确保系统已安装该字体)
fontSettings.getSubstitutionSettings()
.getDefaultFontSubstitution()
.setDefaultFontName("SimSun");
// 应用到当前线程
Document doc = new Document("input.docx");
doc.setFontSettings(fontSettings);
doc.save("output.pdf", SaveFormat.PDF);
}
}
4.2 指定字体来源目录
/**
* 指定自定义字体目录(推荐方案)
*
* 优点:
* - 不污染系统字体
* - 可精确控制使用的字体
* - 应用可自包含运行
*/
public static void setCustomFontFolder() {
FontSettings fontSettings = new FontSettings();
// 添加自定义字体文件夹(可以是项目内部的 resources/fonts)
fontSettings.setFontsFolder("/app/fonts", false);
Document doc = new Document("input.docx");
doc.setFontSettings(fontSettings);
doc.save("output.pdf", SaveFormat.PDF);
}
/**
* 指定多个字体目录
*/
public static void setMultipleFontFolders() {
FontSettings fontSettings = new FontSettings();
// 添加多个字体来源目录
fontSettings.setFontsFolders(
new String[]{
"/usr/share/fonts/chinese",
"/app/resources/fonts",
"/app/libs/fonts"
},
true // 同时扫描子目录
);
Document doc = new Document("input.docx");
doc.setFontSettings(fontSettings);
doc.save("output.pdf", SaveFormat.PDF);
}
4.3 配置字体回退规则
/**
* 配置字体回退规则(精细控制)
*
* 当文档中使用的字体不存在时,按规则逐级回退
*/
public static void configureFontFallback() {
FontSettings fontSettings = new FontSettings();
FontFallbackSettings fallbackSettings = fontSettings.getFallbackSettings();
// 清空默认规则
fallbackSettings.getFallbackFonts().clear();
// 添加回退规则:
// 当文档使用字体范围 0x4E00-0x9FFF(CJK统一汉字)时,
// 依次尝试 SimSun → Microsoft YaHei → Noto Sans CJK SC
fallbackSettings.getFallbackFonts().add(
0x4E00, // Unicode 范围起始(中文)
0x9FFF, // Unicode 范围结束
"SimSun", // 首选
"Microsoft YaHei", // 备用1
"Noto Sans CJK SC" // 备用2
);
// 其他常见 Unicode 范围:
// 0x4E00-0x9FFF → CJK统一汉字
// 0x3000-0x303F → CJK符号和标点
// 0x3040-0x309F → 日文平假名
// 0x30A0-0x30FF → 日文片假名
// 0xAC00-0xD7AF → 韩文音节
// 0x0400-0x04FF → 西里尔字母(俄语)
// 0x0600-0x06FF → 阿拉伯语
Document doc = new Document("input.docx");
doc.setFontSettings(fontSettings);
doc.save("output.pdf", SaveFormat.PDF);
}
/**
* 从配置文件加载回退规则
*/
public static void loadFallbackFromXml() {
FontSettings fontSettings = new FontSettings();
FontFallbackSettings fallbackSettings = fontSettings.getFallbackSettings();
// 从 XML 规则文件加载
fallbackSettings.load("fallback-rules.xml");
Document doc = new Document("input.docx");
doc.setFontSettings(fontSettings);
doc.save("output.pdf", SaveFormat.PDF);
}
4.4 回退规则 XML 配置
<!-- fallback-rules.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<FontFallbackSettings>
<!-- 中文回退规则 -->
<FallbackRule>
<Range Start="0x4E00" End="0x9FFF"/>
<FallbackFont Name="SimSun"/>
<FallbackFont Name="Microsoft YaHei"/>
<FallbackFont Name="Noto Sans CJK SC"/>
<FallbackFont Name="WenQuanYi Micro Hei"/>
</FallbackRule>
<!-- 中文标点符号 -->
<FallbackRule>
<Range Start="0x3000" End="0x303F"/>
<FallbackFont Name="SimSun"/>
<FallbackFont Name="Microsoft YaHei"/>
</FallbackRule>
<!-- 日文平假名/片假名 -->
<FallbackRule>
<Range Start="0x3040" End="0x30FF"/>
<FallbackFont Name="MS Mincho"/>
<FallbackFont Name="SimSun"/>
</FallbackRule>
<!-- 其他所有字符的通用回退 -->
<FallbackRule>
<Range Start="0x0000" End="0xFFFF"/>
<FallbackFont Name="SimSun"/>
<FallbackFont Name="Arial"/>
</FallbackRule>
</FontFallbackSettings>
4.5 完整工具类
import com.aspose.words.*;
import java.io.File;
/**
* Aspose.Words 字体配置工具类
*/
public class AsposeWordHelper {
private static volatile boolean fontConfigured = false;
/**
* 初始化字体配置(全局一次)
*
* @param fontDir 自定义字体目录,若为 null 则尝试自动检测
*/
public static void initFontSettings(String fontDir) {
if (fontConfigured) return;
FontSettings fontSettings = getDefaultFontSettings(fontDir);
// 将 FontSettings 设置为全局默认(对所有 Document 生效)
FontSettings.setDefaultFontSettings(fontSettings);
fontConfigured = true;
}
/**
* 获取默认字体配置
*/
private static FontSettings getDefaultFontSettings(String fontDir) {
FontSettings fontSettings = new FontSettings();
// 1. 设置默认回退字体
fontSettings.getSubstitutionSettings()
.getDefaultFontSubstitution()
.setDefaultFontName("SimSun");
// 2. 添加字体来源目录
String fontsPath = detectFontPath(fontDir);
if (fontsPath != null) {
fontSettings.setFontsFolder(fontsPath, true);
}
// 3. 配置回退规则(额外保护)
FontFallbackSettings fallback = fontSettings.getFallbackSettings();
fallback.getFallbackFonts().add(
0x4E00, 0x9FFF,
"SimSun",
"Microsoft YaHei",
"Noto Sans CJK SC",
"WenQuanYi Micro Hei"
);
return fontSettings;
}
/**
* 自动检测字体目录
*/
private static String detectFontPath(String customDir) {
// 1. 优先使用自定义目录
if (customDir != null && new File(customDir).exists()) {
return customDir;
}
// 2. 常见系统字体目录
String[] commonPaths = {
"/usr/share/fonts",
"/usr/share/fonts/chinese",
"/usr/local/share/fonts",
System.getProperty("user.dir") + "/fonts",
System.getProperty("user.dir") + "/src/main/resources/fonts"
};
for (String path : commonPaths) {
if (new File(path).exists()) {
return path;
}
}
return null;
}
/**
* Word 转 PDF
*/
public static void wordToPdf(String inputPath, String outputPath)
throws Exception {
// 确保字体配置已初始化
initFontSettings(null);
Document doc = new Document(inputPath);
doc.save(outputPath, SaveFormat.PDF);
}
/**
* Word 转 PDF(自定义字体目录)
*/
public static void wordToPdf(String inputPath, String outputPath,
String fontDir) throws Exception {
initFontSettings(fontDir);
Document doc = new Document(inputPath);
doc.save(outputPath, SaveFormat.PDF);
}
/**
* 调试:输出当前字体信息
*/
public static void printFontInfo() {
FontSettings fontSettings = FontSettings.getDefaultFontSettings();
System.out.println("=== Aspose Font Info ===");
System.out.println("Default Font: " +
fontSettings.getSubstitutionSettings()
.getDefaultFontSubstitution()
.getDefaultFontName());
String[] folders = fontSettings.getFontsFolders();
if (folders != null) {
for (String folder : folders) {
System.out.println("Font Folder: " + folder);
}
}
// 列出所有可用字体
String[] fontNames = fontSettings.getFontsSources();
if (fontNames != null) {
System.out.println("Available font sources: " + fontNames.length);
}
}
}
五、解决方案三:Docker 环境
5.1 Dockerfile 方式
# 基于 CentOS 的 Dockerfile
FROM centos:7
# 安装中文字体
RUN yum install -y epel-release \
&& yum install -y \
fontconfig \
mkfontscale \
cjkuni-uming-fonts \
cjkuni-ukai-fonts \
google-noto-cjk-fonts \
&& yum clean all \
&& fc-cache -fv
# 或者从 Windows 复制字体(推荐)
COPY fonts/ /usr/share/fonts/chinese/
RUN mkfontscale /usr/share/fonts/chinese/ \
&& mkfontdir /usr/share/fonts/chinese/ \
&& fc-cache -fv
# 部署应用
COPY app.jar /app/
CMD ["java", "-jar", "/app/app.jar"]
# 基于 Alpine 的 Dockerfile(更小体积)
FROM openjdk:8-jre-alpine
# 安装 fontconfig 和字体
RUN apk add --no-cache fontconfig ttf-dejavu
# 复制中文字体
COPY fonts/ /usr/share/fonts/truetype/chinese/
RUN fc-cache -fv
COPY app.jar /app/
CMD ["java", "-jar", "/app/app.jar"]
# 基于 Ubuntu 的 Dockerfile
FROM ubuntu:20.04
RUN apt-get update \
&& apt-get install -y \
fontconfig \
fonts-wqy-microhei \
fonts-wqy-zenhei \
fonts-noto-cjk \
&& apt-get clean \
&& fc-cache -fv
COPY app.jar /app/
CMD ["java", "-jar", "/app/app.jar"]
5.2 Docker Compose 方式
version: '3.8'
services:
app:
image: my-java-app:latest
volumes:
# 挂载字体目录(不用把字体打包进镜像)
- ./fonts:/usr/share/fonts/custom:ro
environment:
- JAVA_OPTS=-Dfile.encoding=UTF-8
5.3 验证 Docker 字体
# 进入容器验证
docker exec -it <container_id> /bin/bash
# 查看中文字体
fc-list :lang=zh
# 如果看不到字体,可能是 fontconfig 未安装
# 也可以直接检查文件
ls -la /usr/share/fonts/
5.4 推荐:项目中打包字体
<!-- Maven 将字体打包到 JAR 中 -->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>fonts/**/*.ttf</include>
<include>fonts/**/*.ttc</include>
</includes>
</resource>
</resources>
</build>
项目结构中的字体位置:
src/main/resources/fonts/
├── SimSun.ttf
├── msyh.ttf
└── msyhbd.ttf
// 从 classpath 中导出字体到临时目录
public void extractFontsFromClasspath() throws Exception {
String tempFontDir = System.getProperty("java.io.tmpdir")
+ "/aspose-fonts/";
new File(tempFontDir).mkdirs();
// 从 JAR 中复制字体
copyFromClasspath("/fonts/SimSun.ttf",
tempFontDir + "SimSun.ttf");
copyFromClasspath("/fonts/msyh.ttf",
tempFontDir + "msyh.ttf");
// 设置字体路径
FontSettings fontSettings = new FontSettings();
fontSettings.setFontsFolder(tempFontDir, false);
Document doc = new Document("input.docx");
doc.setFontSettings(fontSettings);
doc.save("output.pdf", SaveFormat.PDF);
}
private void copyFromClasspath(String resource, String dest)
throws IOException {
try (InputStream in = getClass().getResourceAsStream(resource);
OutputStream out = new FileOutputStream(dest)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
}
}
六、解决方案四:使用字体文件直接注册
6.1 PhysicalFont 注册
/**
* 直接通过文件路径注册字体(不依赖系统字体目录)
*/
public static void registerFontByFile() {
FontSettings fontSettings = new FontSettings();
// 直接从指定文件加载字体
FontSourceBase fontSource = new FileFontSource(
"/opt/fonts/SimSun.ttf", // 字体文件路径
0, // 优先级(越小越优先)
"Custom SimSun" // 标识名称(可选)
);
fontSettings.setFontsSources(new FontSourceBase[]{fontSource});
Document doc = new Document("input.docx");
doc.setFontSettings(fontSettings);
doc.save("output.pdf", SaveFormat.PDF);
}
/**
* 注册多个字体文件
*/
public static void registerMultipleFonts() {
FontSettings fontSettings = new FontSettings();
// 创建多个字体源
FontSourceBase[] sources = new FontSourceBase[]{
new FileFontSource("/opt/fonts/SimSun.ttf", 0),
new FileFontSource("/opt/fonts/msyh.ttf", 1),
new FileFontSource("/opt/fonts/simsun.ttc", 2),
};
fontSettings.setFontsSources(sources);
Document doc = new Document("input.docx");
doc.setFontSettings(fontSettings);
doc.save("output.pdf", SaveFormat.PDF);
}
6.2 MemoryFontSource(用于加密字体)
/**
* 从内存中加载字体(适用于加密或保护字体文件)
*/
public static void registerFontFromMemory() throws IOException {
// 读取加密的字体文件
byte[] fontData = decryptFontFile("encrypted-simsun.bin");
FontSourceBase memoryFont = new MemoryFontSource(fontData, 0);
FontSettings fontSettings = new FontSettings();
fontSettings.setFontsSources(new FontSourceBase[]{memoryFont});
Document doc = new Document("input.docx");
doc.setFontSettings(fontSettings);
doc.save("output.pdf", SaveFormat.PDF);
}
private static byte[] decryptFontFile(String path) throws IOException {
// 解密逻辑(示例)
byte[] encrypted = Files.readAllBytes(Paths.get(path));
byte[] decrypted = new byte[encrypted.length];
for (int i = 0; i < encrypted.length; i++) {
decrypted[i] = (byte) (encrypted[i] ^ 0x7F); // 简单 XOR 解密
}
return decrypted;
}
七、调试与诊断
7.1 调试工具
/**
* 字体诊断工具——输出当前系统所有可用字体
*/
public void diagnoseFonts() {
// 方法 1:通过 Aspose API
FontSettings fontSettings = FontSettings.getDefaultFontSettings();
System.out.println("=== Aspose Font Settings ===");
System.out.println("Default Font Name: " +
fontSettings.getSubstitutionSettings()
.getDefaultFontSubstitution()
.getDefaultFontName());
// 方法 2:列出所有字体源
FontSourceBase[] sources = fontSettings.getFontsSources();
for (FontSourceBase source : sources) {
System.out.println("Font Source Type: " + source.getType());
System.out.println("Priority: " + source.getPriority());
// 列出该源下的所有字体
PhysicalFontInfo[] fonts = source.getAvailableFonts();
for (PhysicalFontInfo font : fonts) {
System.out.printf(" Font: %s (%s)%n",
font.getFullFontName(), font.getFilePath());
}
}
}
7.2 Linux 字体调试命令
# 查看系统所有字体
fc-list | sort
# 查看中文字体
fc-list :lang=zh | sort
# 查看特定字体是否存在
fc-match SimSun
# 输出:SimSun.ttc: "宋体" "Regular"
# 查看字体文件详情
fc-list -v | grep -i "cjk\|chinese\|simsun\|yahei"
# 查看 fontconfig 配置
fc-conflist
# 测试字体渲染(需要安装 imagemagick)
convert -font SimSun -pointsize 24 \
label:'中文测试' test.png
7.3 Java 调试
# 查看 JVM 能识别的字体
java -cp aspose-words.jar:
com.aspose.words.FontSettings
# 开启 Aspose 调试日志
# 在 log4j.properties 中添加:
log4j.logger.com.aspose.words.FontSettings=DEBUG
7.4 常见调试输出解读
# 正常情况——能找到字体
[DEBUG] Font 'SimSun' found in system fonts collection
[DEBUG] Using font 'SimSun' for CJK characters
# 异常情况——找不到字体
[WARN] Font 'SimSun' is not available
[WARN] Fallback to default font 'Arial'
[ERROR] No suitable font found for Unicode range 0x4E00-0x9FFF
八、常见问题排查
8.1 问题对照表
| 问题 | 现象 | 原因 | 解决方案 |
|---|---|---|---|
| 所有中文变方块 | □□□ | 无中文字体 | 安装字体 + fc-cache |
| 部分中文变方块 | 某些字正常某些方块 | 字体不全 | 换用完整字体(如 Noto CJK) |
| 中文显示为空白 | 文字不可见 | 字体渲染失败 | 检查字体文件权限 |
| 加粗中文乱码 | 粗体显示异常 | 未安装粗体版本 | 复制 msyhbd.ttf 等粗体文件 |
| 斜体中文乱码 | 斜体显示异常 | 无斜体字体 | 设置 getSubstitutionSettings() |
| Docker 乱码 | 容器内乱码 | 基础镜像无字体 | Dockerfile 安装字体 |
| 仅在特定 Doc 乱码 | 一个文档乱码另一个正常 | 文档嵌入了字体子集 | 检查文档嵌入字体 |
| PDF 体积过大 | PDF 文件异常大 | 嵌入了大量字体 | 设置字体子集化 |
8.2 字体文件完整性检查
# 检查 ttf 文件是否损坏
file simsun.ttc
# 输出:TrueType font collection data
# 检查 ttc 中包含的字体列表
python -c "
from fontTools.ttLib import TTFont
font = TTFont('simsun.ttc')
font.keys()
"
8.3 快速环境修复脚本
#!/bin/bash
# fix-chinese-fonts.sh
# 一键修复 CentOS 中文乱码
echo "=== 开始修复中文乱码 ==="
# 1. 创建字体目录
mkdir -p /usr/share/fonts/chinese
# 2. 如果没有字体文件,尝试从网络下载
if [ ! -f "/usr/share/fonts/chinese/SimSun.ttf" ]; then
echo "下载 Noto CJK 字体..."
yum install -y google-noto-cjk-fonts
fi
# 3. 安装 fontconfig
yum install -y mkfontscale fontconfig
# 4. 生成字体缓存
cd /usr/share/fonts/chinese
mkfontscale 2>/dev/null || true
mkfontdir 2>/dev/null || true
fc-cache -fv
# 5. 验证
echo "=== 已安装的中文字体 ==="
fc-list :lang=zh 2>/dev/null | head -10
echo "=== 修复完成 ==="
echo "如果仍存在问题:"
echo "1. 将 Windows 的 C:\\Windows\\Fonts 复制到 /usr/share/fonts/chinese/"
echo "2. 重新运行本脚本"
echo "3. 重启应用"
8.4 快速排查清单
-
fc-list :lang=zh能否看到中文字体 - 字体文件权限是否为
644/755 - 字体目录是否在 Aspose 的搜索路径中
- 是否在
FontSettings中设置了DefaultFontName - Docker 中是否安装了
fontconfig - Docker 中是否执行了
fc-cache -fv - 项目中是否打包了备用字体
- 文档中是否使用了稀有字体(如特殊艺术字)
九、总结
9.1 解决方案优先级
方案一:环境装字体 ✅ 一劳永逸,推荐
├─ 复制 Windows 字体 ✅ 最完整
└─ yum/apt 安装包 ✅ 方便但字体可能不全
方案二:Aspose 代码配置 ✅ 双重保险,强烈推荐
├─ setDefaultFontName() ✅ 设置回退字体
├─ setFontsFolder() ✅ 自定义字体目录
├─ FontFallbackSettings ✅ 精细回退规则
└─ FileFontSource ✅ 直接注册字体文件
方案三:Docker 配置 ✅ 容器化部署
├─ Dockerfile 安装 ✅ 不可变镜像
└─ Volume 挂载 ✅ 灵活替换
方案四:打包在项目中 ✅ 自包含,无环境依赖
├─ resources/fonts/ ✅ JAR 内嵌字体
└─ 运行时解压 ✅ 独立运行
9.2 最佳实践
/**
* 生产环境推荐配置
*/
@PostConstruct
public void initAsposeFonts() {
FontSettings fontSettings = new FontSettings();
// 1. 默认回退字体
fontSettings.getSubstitutionSettings()
.getDefaultFontSubstitution()
.setDefaultFontName("SimSun");
// 2. 目录优先级:项目字体 > 系统字体
String projectFonts = System.getProperty("user.dir") + "/fonts";
if (new File(projectFonts).exists()) {
// 项目字体目录(最高优先级)
fontSettings.setFontsFolder(projectFonts, false);
} else {
// 回退到系统字体目录
fontSettings.setFontsFolder("/usr/share/fonts", true);
}
// 3. CJK 回退规则
FontFallbackSettings fallback = fontSettings.getFallbackSettings();
fallback.getFallbackFonts().add(
0x4E00, 0x9FFF,
"SimSun",
"Microsoft YaHei",
"WenQuanYi Micro Hei",
"Noto Sans CJK SC"
);
FontSettings.setDefaultFontSettings(fontSettings);
log.info("Aspose font settings initialized");
}
9.3 各平台一站式对照
| 步骤 | Windows | Linux (CentOS) | Linux (Ubuntu) | Docker (Alpine) | Docker (CentOS) |
|---|---|---|---|---|---|
| 安装字体工具 | 无需 | yum install mkfontscale fontconfig | apt install fontconfig | apk add fontconfig | 同 CentOS |
| 安装中文字体 | 系统自带 | yum install google-noto-cjk-fonts | apt install fonts-noto-cjk | 复制字体文件 | 同 CentOS 并复制字体 |
| 字体目录 | C:\Windows\Fonts | /usr/share/fonts | /usr/share/fonts | /usr/share/fonts | /usr/share/fonts |
| 缓存命令 | 无需 | fc-cache -fv | fc-cache -fv | fc-cache -fv | fc-cache -fv |
| Aspose 设置 | 非必需(可选) | 必需 | 必需 | 必需 | 必需 |
9.4 核心要点
- 环境是基础:确保 Linux/Docker 安装了中文字体(
fc-list :lang=zh验证) - 代码是保障:始终在 Aspose 中设置
DefaultFontName和自定义字体目录 - 字体完整:粗体(Bold)、斜体(Italic)版本都需要安装
- 权限正确:字体文件需要可读权限(
chmod 644) - 缓存更新:安装字体后执行
fc-cache -fv - 自包含:关键项目将字体打包在 JAR 中,避免环境依赖
- 验证:转换后打开 PDF 检查所有中文是否正常
文章讲述了在CentOS服务器上使用Aspose.Word转换Word文件至PDF时遇到的中文乱码问题,原因在于Linux缺少对应字库。提供了详细的解决方案,包括安装字库、更新字体缓存和设置字体权限等步骤。

6872

被折叠的 条评论
为什么被折叠?



