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

news2025/1/4 11:57:22

哎呀,今天忙到飞起,文章晚点更新啦!不过好消息是,我们的小程序用户终于突破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帮工办

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2269984.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

操作系统课后题总复习

目录 一、第一章 1.1填空题 1.2单项选择题 1.3多项选择题 1.4判断题 1.5名词解释 1.6简答题 二、第二章 2.1填空题 2.2单项选择题 2.3 多项选择题 2.4判断题 2.5名词解释 2.6简答题 三、第三章 3.1填空题 3.2单项选择题 3.3多项选择题 3.4判断题 3.5名词解…

C语言期末复习笔记(下)

目录 九、指针 1.指针变量的定义和初始化 2.间接寻址符* 3.按值调用和按址调用 4.实例 5.函数指针 6.指针变量和其它类型变量的对比 十、字符串 1.字符串常量 2.字符串的存储 3.字符指针 4.字符串的访问和输入/输出 5.字符串处理函数 (1)str…

保姆级教程Docker部署ClickHouse镜像

目录 1、安装Docker及可视化工具 2、创建挂载目录 3、获取配置文件 4、运行ClickHouse容器 5、Compose运行ClickHouse容器 6、查看ClickHouse运行状态 7、安装包部署 1、安装Docker及可视化工具 Docker及可视化工具的安装可参考:Ubuntu上安装 Docker及可视化…

飞牛私有云APP结合cpolar内网穿透技术实现远程连接本地fnOS NAS

文章目录 前言1. 本地连接测试2. 飞牛云安装Cpolar3. 配置公网连接地址4. 飞牛云APP连接测试5. 固定APP远程地址6. 固定APP地址测试 前言 现在生活和工作中的各种设备都变得越来越智能,而数据存储的需求也随之剧增。想象一下:你正在外地出差&#xff0c…

计算机网络 (17)点对点协议PPP

一、PPP协议的基本概念 PPP协议最初设计是为两个对等节点之间的IP流量传输提供一种封装协议,它替代了原来非标准的第二层协议(如SLIP)。在TCP/IP协议集中,PPP是一种用来同步调制连接的数据链路层协议(OSI模式中的第二层…

RC充电电路仿真与分析

RC充电原理 下图是一个常见的RC充电电路:(假设R10K,C100nF) SW断开时,这个电路处于断路状态,C既没有充电也没有放电;SW闭合时,直流电源5V为电容C充电; 充电时电容两端…

全新免押租赁系统助力商品流通高效安全

内容概要 全新免押租赁系统的推出,可以说是一场商品流通领域的小革命。想象一下,不再为押金烦恼,用户只需通过一个简单的信用评估,就能快速租到所需商品,这种体验简直令人惊喜!这个系统利用代扣支付技术&a…

c++领域展开第八幕——类和对象(下篇 初始化列表、类型转换、static成员)超详细!!!!

文章目录 前言一、初始化列表二、类型转换三、static成员总结 前言 上篇博客我们实现了一个简单的日期类,基本的类和对象是清楚了 今天我们再来学习后面的一些类和对象的语法,慢慢的完善所学的东西 fellow me 一、初始化列表 • 之前我们实现构造函数时…

Linux-Ubuntu之RGBLCD显示屏

Linux-Ubuntu之RGBLCD显示屏 一,实现原理二,驱动代码三,总结1.c语言知识 一,实现原理 采用的是4.3寸 800480显示屏,即每行有800个像素点,每列有480个像素点,外接时钟信号,控制刷新频…

JVM 主要组成部分与内存区域

一、JVM 主要组成部分: JVM的主要包含两个组件和两个子系统,分别为: (1)本地库接口(Native Interface):与native lib(本地方法库)交互,融合其他编程语言为Java所用,是与其它编程语言…

如何在鸿蒙本地模拟器中使用HDC工具

引言 HDC是指华为设备连接(Huawei Device Connector)工具。它的作用类似Android开发的ADB工具。在华为鸿蒙(HarmonyOS)操作系统的开发过程中,HDC工具起到了至关重要的作用。它允许开发者在开发主机(如 PC&…

ruoyi 分页 查询超出后还有数据; Mybatis-Plus 分页 超出后还有数据

修改:MybatisPlusConfig 类中 分页合理化修改为:paginationInnerInterceptor.setOverflow(false);

Unity中实现转盘抽奖效果(二)

如果要使转盘停止时转到到指定位置,应该如何做? 实现思路: 也就是在需要停止的分数的区间范围内,随机一个角度值,然后反推需要在哪个角度开始减速,如果转盘的当前角度和需要开始减速的角度有差值&#xf…

苍穹外卖04——Redis初入门 在店铺打烊or营业状态管理功能中的使用

Redis入门 redis简介 它以键值对的形式存储数据在内存中,并且以极高的性能和灵活性而著称,通常用于缓存、消息代理以及持久化数据。 - 基于内存存储,读写性能高- 适合存储热点数据(热点商品、资讯、新闻)- 企业应用广泛Windows版下载地址:https://github.com/microsoft…

深度学习每周学习总结R2(RNN-天气预测)

🍨 本文为🔗365天深度学习训练营 中的学习记录博客R5中的内容,为了便于自己整理总结起名为R2🍖 原作者:K同学啊 | 接辅导、项目定制 目录 0. 总结1. RNN介绍a. 什么是 RNN?RNN 的一般应用场景 b. 传统 RNN …

CUDA与Microsoft Visual Studio不兼容问题

简介:在安装一些 python库时,涉及到第三方库(特别是需要引用 C 代码)时,通常的安装方式会涉及到编译过程,通常称为"源代码安装"(source installation),或是 “…

WordPress网站中如何修复504错误

504网关超时错误是非常常见的一种网站错误。这种错误发生在上游服务器未能在规定时间内完成请求的情况下,对访问者而言,出现504错误无疑会对访问体验大打折扣,从而对网站的转化率和收入造成负面影响。 504错误通常源于服务器端或网站本身的问…

Springboot 升级带来的Swagger异常

当升级到Springboot 2.6.0 以上的版本后,Swagger 就不能正常工作了, 启动时报如下错误。当然如果你再使用sping boot Actuator 和 Springfox, 也会引起相关的NPE error. (github issue: https://github.com/springfox/springfox/issues/3462) NFO | jvm 1 | 2022/04…

发现API安全风险,F5随时随地保障应用和API安全

分析数据显示,目前超过90%的基于Web的网络攻击都以API端点为目标,试图利用更新且较少为人所知的漏洞,而这些漏洞通常是由安全团队未主动监控的API所暴露。现代企业需要一种动态防御策略,在风险升级成代价高昂、令人警惕且往往无法…

【数据结构】(Python)差分数组。差分数组与树状数组结合

差分数组: 基于原数组构造的辅助数组。用于区间修改、单点查询。区间修改的时间复杂度O(1)。单点查询的时间复杂度O(n)。差分数组的元素:第一个元素等于原数组第一个元素,从第二个元素开始是原数组对应下标的元素与前一个元素的差&#xff0…