微信流量主挑战:用户数30!新增文档转化功能,解决docker运行jar包报错SimSun找不到的问题(新纪元5)

哎呀,今天忙到飞起,文章晚点更新啦!不过好消息是,我们的小程序用户终于突破30啦,感谢大家的支持!而且,大家期待已久的文档转化功能明天就要上线啦,目前支持word转pdf,pdf转图片,xlsx转pdf。

记录下难点,有个问题是在docker部署时候word转pdf没有中文乱码,控制台报错

024-12-27 23:59:11.769 WARN 1 --- [nio-8004-exec-3] org.docx4j.fonts.RunFontSelector : Font 'SimSun' is not mapped to a physical font. 2024-12-27 23:59:11.788 WARN 1 --- [nio-8004-exec-3] org.docx4j.fonts.RunFontSelector : Font 'Cambria' is not mapped to a physical font. 2024-12-27 23:59:11.807 WARN 1 --- [nio-8004-exec-3] org.docx4j.fonts.fop.util.FopConfigUtil : Document font Cambria is not mapped to a physical font!

大概意思是某个字体映射没有找到,网上说的大概流程是查看docker字体,没有就去下载之类的

但是我是通过window的c盘fonts转过去的,容器中也有字体了

通过window的c盘fonts转到容器

命令如下,docker容器外进行

docker cp /usr/share/fonts/truetype/dejavu/. eblog:/usr/share/fonts/truetype/chinese/

eblog为你的容器名称,/usr/share/fonts/truetype/dejavu/是以下部分

/usr/share/fonts/truetype/chinese/为容器内的文件夹

通过上述命令可以将字体库放入docker容器中了

但是后续打包好jar包后运行,还是会报SimSun找不到的错误,导致转pdf全是乱码

即使是直接将对应的字体文件引入都不行,这里我设置了字体映射注册也不行

复制代码
        try {
            // 设置字体映射
            fontMapper.put("SimSun", PhysicalFonts.get("/usr/share/fonts/truetype/chinese/SIMSUN.TTC"));

            // 检查是否成功
            PhysicalFont font = PhysicalFonts.get("SimSun");
            if (font == null) {
                System.out.println("Failed to map SimSun to physical font.");
            } else {
                System.out.println("SimSun mapped to " + font.getName());
            }

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Failed to map fonts.");
        }

通过获取系统中所有已注册的字体并打印出来,发现并没有将SimSun注册

复制代码
            PhysicalFonts.getPhysicalFonts().forEach((key, font) -> {
                System.out.println("Font: " + key);
            });

我的解决办法就是将sisum.ttc文件一起打包上去,将simsun.ttc放在resources下的fonts中

获取字体文件的 URL并且注册fontMapper.put("宋体", PhysicalFonts.get("SimSun"));

复制代码
// 获取字体文件的 URL,路径相对于类路径(即 resources 目录)
        ClassLoader classLoader = FileServiceImpl.class.getClassLoader();
        URL fontUrl = classLoader.getResource("fonts/simsun.ttc");
        if (fontUrl == null) {
            throw new RuntimeException("Resource not found: " + fontUrl);
        }
        fontMapper.put("宋体", PhysicalFonts.get("SimSun"));

打包运行转换成功

完整代码如下

复制代码
private String convertWordToPdf(String filePath) throws Exception {
        FileOutputStream fileOutputStream = null;
        try {
            // 获取当前时间戳
            String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());

            // 获取文件名(去掉路径和扩展名)
            File file = new File(filePath);
            String fileName = file.getName().replaceAll("\\.docx$", "");

            // 创建带时间戳的pdf路径,文件保存到fileDir目录下
            String pdfPath = fileDir + fileName + "_" + timestamp + ".pdf";

            // 进行文件转换
            fileOutputStream = new FileOutputStream(new File(pdfPath));
            WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(file);
            setFontMapper(mlPackage);
            Docx4J.toPDF(mlPackage, fileOutputStream);

            System.out.println("PDF转换成功,文件保存为:" + pdfPath);

            // 返回生成文件路径
            return fileName + "_" + timestamp + ".pdf";
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("转换失败");
            throw new UnsupportedOperationException("Word 转 PDF 的功能尚未实现: " + filePath);
        } finally {
            IOUtils.closeQuietly(fileOutputStream);
        }
    }

    private static void setFontMapper(WordprocessingMLPackage mlPackage) throws Exception {
        Mapper fontMapper = new IdentityPlusMapper();

        // 获取字体文件的 URL,路径相对于类路径(即 resources 目录)
        ClassLoader classLoader = FileServiceImpl.class.getClassLoader();
        URL fontUrl = classLoader.getResource("fonts/simsun.ttc");
        if (fontUrl == null) {
            throw new RuntimeException("Resource not found: " + fontUrl);
        }

        // 使用 PhysicalFonts 添加字体
        PhysicalFonts.addPhysicalFonts("SimSun", fontUrl);
        fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
        fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
        fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft Yahei"));
        fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
        fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));
        fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));
        fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
        fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
        fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
        fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));
        fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));
        fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));
        fontMapper.put("等线", PhysicalFonts.get("SimSun"));
        fontMapper.put("等线 Light", PhysicalFonts.get("SimSun"));
        fontMapper.put("华文琥珀", PhysicalFonts.get("STHupo"));
        fontMapper.put("华文隶书", PhysicalFonts.get("STLiti"));
        fontMapper.put("华文新魏", PhysicalFonts.get("STXinwei"));
        fontMapper.put("华文彩云", PhysicalFonts.get("STCaiyun"));
        fontMapper.put("方正姚体", PhysicalFonts.get("FZYaoti"));
        fontMapper.put("方正舒体", PhysicalFonts.get("FZShuTi"));
        fontMapper.put("华文细黑", PhysicalFonts.get("STXihei"));
        fontMapper.put("宋体扩展",PhysicalFonts.get("simsun-extB"));
        fontMapper.put("仿宋_GB2312",PhysicalFonts.get("FangSong_GB2312"));
        fontMapper.put("新細明體",PhysicalFonts.get("SimSun"));
        //解决宋体(正文)和宋体(标题)的乱码问题
        PhysicalFonts.put("PMingLiU", PhysicalFonts.get("SimSun"));
        PhysicalFonts.put("新細明體", PhysicalFonts.get("SimSun"));
        // 设置字体映射
        mlPackage.setFontMapper(fontMapper);

    }

有兴趣体验小程序,搜索Listen Hui帮工办

相关推荐
微爱帮监所写信寄信11 小时前
微爱帮监狱寄信写信工具照片高清处理技术架构
开发语言·人工智能·网络协议·微信·php
孙严Pay15 小时前
代付业务解析
笔记·科技·计算机网络·其他·微信
说私域16 小时前
基于开源AI大模型AI智能名片S2B2C商城小程序的内容价值生成与多点选择传播策略研究
人工智能·微信·小程序·开源
微爱帮监所写信寄信16 小时前
微爱帮监狱寄信写信小程序PHP底层优化框架
java·开发语言·数据库·spring·微信·php·mybatis
孙严Pay1 天前
分享三种不同的支付体验,各自有着不同的特点与适用场景。
笔记·科技·计算机网络·其他·微信
资深数据库专家1 天前
window 11 检测到一个 TDI 筛选器(\Driver\gwredirector)。该筛选器尚未通过 Microsoft 认证 。 如何解决
经验分享·微信·微信公众平台·新浪微博
陈思杰系统思考Jason1 天前
2025年的自己
百度·微信·微信公众平台·新浪微博·微信开放平台
梦想的旅途22 天前
企业微信开发笔记:外部群主动推送消息的逻辑实现
微信·自动化·企业微信
弓乙图2 天前
金刚经的核心思想
经验分享·微信