docx4j word转pdf

docx4j word转pdf

WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is);
这行代码 首次加载很慢 需要8s左右。第二次请求就正常,有什么办法能优化?


```java



public static void word2Pdf(InputStream is, String pdfPath) {
        OutputStream os = null;
        try {
            WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is);
            Mapper fontMapper = new IdentityPlusMapper();

            //加载字体文件(解决linux环境下无中文字体问题)
            if (PhysicalFonts.get("SimSun") == null) {
                PhysicalFonts.addPhysicalFonts("FangSong_GB2312", WordUtils.class.getResource("/font/GB2312.ttf"));
            }

            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"));
            PhysicalFont simsunFont = PhysicalFonts.get("SimSun");
            fontMapper.put("SimSun", simsunFont);
            mlPackage.setFontMapper(fontMapper);
            os = new java.io.FileOutputStream(pdfPath);
            FOSettings foSettings = Docx4J.createFOSettings();
            foSettings.setWmlPackage(mlPackage);
            Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);
            is.close();//关闭输入流
            os.close();//关闭输出流
        } catch (Exception e) {
            e.getMessage();
            try {
                if (is != null) {
                    is.close();
                }
                if (os != null) {
                    os.close();
                }
            } catch (Exception ex) {
                ex.getMessage();
            }
        }
    }

第一次加载耗时长是因为docx4j需要初始化一些内容。可以通过以下方式来优化:

1.第一次请求后预加载docx4j,使不必每次请求都重新初始化;
2.减少字体映射的数量,只加载实际使用的字体;
3.使用预先配置的docx4j的配置文件,而不是每次请求都重新配置;
4.关闭debug模式,减少打印信息的量。

首次调用load方法 耗时较长优化方向:
1、减小不必要的启动项
2、提前进行预启动
3、方法集成,直接引用

该回答引用ChatGPT
请参考下面的解决方案,如果有帮助,还请点击 “采纳” 感谢支持!

可以考虑使用一些优化方法来提高加载速度:

1、缓存:将加载好的文件进行缓存,下次请求时直接从缓存中读取,避免了重复加载的时间。
2、压缩文件:如果文件较大,可以考虑对文件进行压缩,加载时间缩短。
3、使用更快的加载方法:可以考虑使用更快的加载方法来加载文件,减少加载时间。
4、具体优化方法需要根据实际情况来确定,可以考虑需求以及代码的实现情况。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
代码优化:
1、将字体的配置移到独立的方法中,把配置单独处理,方便修改和维护。

2、将try-catch中的代码抽离出来,提高代码的可读性。

3、使用Java 7以上的自动关闭资源特性,简化代码,并且保证流的关闭。

public static void word2Pdf(InputStream is, String pdfPath) {
    try (OutputStream os = new FileOutputStream(pdfPath)) {
        WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is);
        Mapper fontMapper = createFontMapper();
        mlPackage.setFontMapper(fontMapper);
        FOSettings foSettings = Docx4J.createFOSettings();
        foSettings.setWmlPackage(mlPackage);
        Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static Mapper createFontMapper() throws Exception {
    Mapper fontMapper = new IdentityPlusMapper();
    if (PhysicalFonts.get("SimSun") == null) {
        PhysicalFonts.addPhysicalFonts("FangSong_GB2312", WordUtils.class.getResource("/font/GB2312.ttf"));
    }
    fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
    ...
    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"));
    PhysicalFont simsunFont = PhysicalFonts.get("SimSun");
    fontMapper.put("SimSun", simsunFont);
    return fontMapper;
}


根据您描述的问题,在使用docx4j的过程中,发现首次加载很慢的问题,这是由于首次加载需要初始化其中的JAXB content 。如果需要减少加载的时间,可以尝试如下方法:
1.加大jvm的内存大小,或者检查电脑cpu或内存是否过小。
2.如果可以,可以采用预加载的方式提前加载过来。
3.如果可以,把docx4j源码中,不需要的包删除。

要优化您提供的代码中 WordprocessingMLPackage 的加载时间,您可以考虑以下方法:

缓存对象:首次加载 WordprocessingMLPackage 后,您可以缓存对象以供后续使用。这样,您可以在将来的请求中重复使用同一对象,而不必每次都重新加载它。

增加内存分配:您可以增加 JVM 可用的内存量,因为这可能有助于加快初始加载时间。您可以通过在启动 JVM 时使用 -Xmx 选项来执行此操作,例如,通过运行以下命令:java -Xmx1024m -jar myapp.jar

优化文件格式:.docx格式的文字处理文件可能很大且复杂,这会减慢加载过程。您可以尝试将文件转换为更优化的格式,例如.pdf或.html,这可能会导致更快的加载时间。

并行处理:如果需要加载多个文字处理文件,可以考虑并行加载它们以减少整体加载时间。

升级到最新版本的 docx4j:较新版本的库可能包含性能优化、错误修复和其他有助于加快加载过程的改进。

请注意,最佳解决方案将取决于您的特定用例,您可能需要尝试不同的方法或方法组合来找到最适合您的方法。

如果耗时找不到有效的优化方案,建议就更换方法嘛,不就是将word转pdf,我给你推荐一篇,题主你参考一下,若有帮助,还望采纳,点击回答右侧采纳即可。
1、https://blog.csdn.net/weixin_43970743/article/details/125906262
2、https://blog.csdn.net/weixin_43970743/article/details/125907235