You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Flying Saucer添加自定义字体后生成PDF损坏显示乱码

Flying Saucer 引入自定义字体后PDF损坏、浏览器显示乱码的解决方法

常见问题修正

  • 修正字体路径的加载逻辑
    Flying Saucer FontResolver 的 addFont() 方法默认按文件系统路径查找字体,不会自动把传入的字符串识别为classpath资源路径。当前代码里直接传/fonts/Montserrat-Regular.ttf这类路径,实际查找的目标是应用启动工作目录下的对应文件夹,根本定位不到打包在classpath、jar包内部的字体文件。
    部分版本的Flying Saucer在找不到字体时,不会抛出显式的可读异常,反而会直接生成结构损坏的PDF流,表现就是浏览器不触发下载、页面全是乱码符号。
    正确的加载方式是通过类加载器获取字体的输入流,调用支持流参数的addFont重载方法完成注册:
    // 逐个加载classpath下的字体资源,自动关流
    try (InputStream regularStream = getClass().getResourceAsStream("/fonts/Montserrat-Regular.ttf");
         InputStream italicStream = getClass().getResourceAsStream("/fonts/Montserrat-Italic.ttf");
         InputStream boldStream = getClass().getResourceAsStream("/fonts/Montserrat-Bold.ttf");
         InputStream boldItalicStream = getClass().getResourceAsStream("/fonts/Montserrat-BoldItalic.ttf")) {
        // 注册时显式指定编码与嵌入参数,避免参数语义歧义
        renderer.getFontResolver().addFont(regularStream, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        renderer.getFontResolver().addFont(italicStream, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        renderer.getFontResolver().addFont(boldStream, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        renderer.getFontResolver().addFont(boldItalicStream, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    }
    
  • 保证字体元数据和CSS声明匹配
    不少ttf字体的文件名和内部存储的字体家族名存在偏差,如果CSS中写的font-family: 'Montserrat'和字体内部的实际家族名不一致,会导致字体匹配失败,触发错误的回退逻辑生成损坏文件。可通过常规字体查看工具确认Montserrat内部的家族名,保证CSS声明完全匹配,同时不要在CSS中引入和Montserrat冲突的其他字体声明。
  • 排查响应流的异常写入问题
    字体注册失败时抛出的异常堆栈,如果没有被正确捕获,会直接写入到本该输出PDF的响应流中。此时浏览器收到的不是合法的PDF文件,而是带错误信息的文本内容,自然不会触发下载,反而会因为按PDF格式解析文本流显示出各类乱码符号。需要在PDF生成全链路加上异常捕获,确保只有合法的PDF字节流会被写入响应输出,同时配置正确的响应头:
    response.setContentType("application/pdf");
    response.setHeader("Content-Disposition", "attachment; filename=generated.pdf");
    
  • 解决字体格式兼容问题
    部分渠道下载的Montserrat ttf文件带有特殊子集压缩格式,Flying Saucer基于的旧版iText内核对这类格式支持不完善,嵌入字体时会生成结构损坏的PDF文件。可将对应ttf文件通过常规字体编辑器打开后,重新导出为无子集压缩的标准ttf/otf格式,替换原有字体文件重试。

匹配的CSS参考写法

html {
  font-family: 'Montserrat', sans-serif;
  font-size: 14px;
}

内容的提问来源于stack exchange,提问作者Wim Deblauwe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 06:45:05