微信流量主挑战:用户数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帮工办

相关推荐
陈思杰系统思考Jason6 小时前
短期与长期利益平衡
百度·微信·微信公众平台·新浪微博·微信开放平台
陈思杰系统思考Jason2 天前
系统思考修炼之旅
百度·微信·微信公众平台·新浪微博·微信开放平台
前端伪大叔3 天前
第26篇:爆赚利器!三步搞定 Freqtrade 核心买卖信号,手把手教你写自动交易策略!
javascript·mysql·微信
陈思杰系统思考Jason4 天前
时硕科技,隐形冠军的修炼之道
百度·微信·微信公众平台·新浪微博·微信开放平台
开发加微信:hedian1164 天前
“十五五”规划前瞻:短剧小程序系统开发的技术浪潮与开发新机遇
微信·小程序
易晨 微盛·企微管家5 天前
生鲜电商企业微信私域代运营:从去中心化运营看微盛AI·企微管家SCRM适配案例
人工智能·微信·企业微信
Jacky【YL】6 天前
微信支付和微信退款源码
微信·微信支付·微信退款·支付回调·退款回调
晓晓莺歌6 天前
微信H5开发,提示redirect_uri参数错误
微信
错把套路当深情6 天前
Kotlin基础类型扩展函数使用指南
python·微信·kotlin
微信api接口介绍6 天前
微信个人发消息api
运维·服务器·开发语言·前端·网络·微信·ipad