使用OpenHTMLToPDF生成PDF时特定字符显示为#的问题排查求助
解决OpenHTMLToPDF中DejaVuSans字体无法显示特殊字符的问题
我帮你分析下这个问题——PDF里出现#替代字符,本质是OpenHTMLToPDF找不到对应字符的字体字形(glyph)。虽然DejaVuSans确实支持土耳其语的ı, ş, İ这些字符,但你的配置大概率有这几处问题:
1. 字体加载时机错误(最核心的问题)
你当前的代码是先构建渲染器,再添加字体:
pdfRendererBuilder.buildPdfRenderer().getFontResolver().addFont(...)
但OpenHTMLToPDF的渲染器一旦build完成,字体上下文就已经初始化,后续添加的字体根本不会生效。正确的做法是在构建渲染器之前,通过PdfRendererBuilder直接配置字体:
try (InputStream is = pdfTtfFile.getInputStream()) { // 先通过builder注册字体,再build渲染器 pdfRendererBuilder.useFont(() -> is, "deja-sans"); } catch (IOException e) { logger.warn("error while loading DejaVuSans_1.ttf font", e); } // 最后构建渲染器 PdfRenderer renderer = pdfRendererBuilder.buildPdfRenderer();
useFont是官方推荐的便捷方法,能确保字体在渲染器初始化时就被正确加载。
2. 确认字体文件的完整性
检查你用的DejaVuSans_1.ttf是不是完整的DejaVu Sans常规字体:
- 有些字体文件是子集化的(只包含常用字符),如果你的TTF是裁剪过的,可能刚好缺失土耳其语的特殊字符
- 建议替换成完整的DejaVu Sans字体文件(常规版本大小约1.4MB),避免字符缺失
3. 验证字体名称与CSS的匹配
虽然你设置了别名deja-sans,但有时候别名匹配可能出现问题。可以尝试直接使用字体的内部名称:
- DejaVu Sans的内部名称是
"DejaVu Sans"(注意空格和大小写),修改代码:
pdfRendererBuilder.useFont(() -> is, "DejaVu Sans");
然后CSS同步修改:
body { font-family: 'DejaVu Sans', sans-serif; }
这样能彻底避免别名匹配的潜在问题。
4. 检查HTML的字符编码
确保你的HTML文件是以UTF-8编码保存的,并且在头部声明编码:
<meta charset="UTF-8">
如果HTML本身编码错误,OpenHTMLToPDF解析到的就是乱码,自然找不到对应的字形。
按上面的步骤调整后,应该就能正确显示Fıstıkçı Şahap İlkay Günel这些内容了。
内容的提问来源于stack exchange,提问作者İlkay Gunel
相关产品推荐
相关产品推荐

