docx4j 将word2007版转为pdf

目的

使用docx4j可以将 docx, pptx, xlsx 文件转为 pdf

添加依赖

首先,在pom.xml中引入相关依赖

<dependency>
    <groupId>org.docx4j</groupId>
    <artifactId>docx4j-export-fo</artifactId>
    <version>11.2.9</version>
</dependency>
<dependency>
    <groupId>org.docx4j</groupId>
    <artifactId>docx4j-JAXB-ReferenceImpl</artifactId>
    <version>11.2.9</version>
</dependency>

转PDF

下面两套代码均可以实现

代码1

private static boolean docx4jConvert(String src, String dst) {
    OutputStream os = null;
    try {
        File srcFile = new File(src);
        WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(srcFile);
        FOSettings foSettings = Docx4J.createFOSettings();
        foSettings.setOpcPackage(mlPackage);
        OutputStream os = new FileOutputStream(dst);
        Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);
        return true;
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (Docx4JException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
    	if(os != null) {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
    }
    return false;
}

代码2

private static boolean docx4jConvert(String src, String dst) {
    OutputStream os = null;
    try {
        File srcFile = new File(src);
        WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(srcFile);
        os = new FileOutputStream(dst);
        Docx4J.toPDF(mlPackage, os);
        return true;
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (Docx4JException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
    	if(os != null) {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
    }
    return false;
}

解决乱码问题

运行上面代码,程序打印一切正常,并输出pdf文件。但是你会发现PDF里,只要有中文的地方,都是乱码。这是由于在转换时没有找到对应字体导致的
在这里插入图片描述
PDF乱码部分节选
在这里插入图片描述

因此我们需要在这里手动加载中文字体。如果该字体不存在于系统的字体库,我们需要使用 addPhysicalFonts 方法进行加载

    /**
     * 设置字体,解决中文乱码的问题
     */
    private static void setFontMapper(WordprocessingMLPackage mlPackage) throws Exception {
        Mapper fontMapper = new IdentityPlusMapper();
        // 加载本地字体
        //PhysicalFonts.addPhysicalFonts("SimSun", new URL("/fonts/SIMSUN.TTC"));
        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("simsun-extB"));
        fontMapper.put("仿宋",PhysicalFonts.get("FangSong"));
        fontMapper.put("仿宋_GB2312",PhysicalFonts.get("FangSong_GB2312"));
        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);
    }

之后即可正常显示了

转换限制

docx4j 只能转换 docx/pptx/xlsx 这三种类型的文件,如果你使用诸如 txt、doc 这类文件,就会报如下错误
在这里插入图片描述

ClassNotFoundException

javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
在这里插入图片描述
这是由于,你在 pom.xml 中只引用了 docx4j-export-fo,却没用引用 JAXB 的实现。在 docx4j 的官网中可以找到该模块的实现库 docx4j-JAXB-ReferenceImpl 。注意,不要去引用 Javax 的那些 JAXB 库或者其他相关库,因为这样会引入更多错误
在这里插入图片描述

注意:如果你的代码用的是JDK8,那么只能使用上图8.3.1的版本;如果是JDK11及以上那么使用11.2.9版本。版本使用错会导致编译不过

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
使用 docx4j 进行 WordPDF 有很多种方法,其中一种简单的方法是使用 docx4j-export-fo 插件,该插件可以将 Word 转换成 XSL-FO 格式,然后使用 Apache FOP 将 XSL-FO 转换成 PDF 格式。 下面是一个简单的示例: ```java import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import org.docx4j.convert.out.FOSettings; import org.docx4j.convert.out.FOSettings.MimeType; import org.docx4j.convert.out.common.writer.AbstractMessageWriter; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; public class WordToPdfConverter { public static void convert(String inputFilePath, String outputFilePath) { try { WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File(inputFilePath)); // 设置输出参数 FOSettings foSettings = Docx4J.createFOSettings(); foSettings.setMimeType(MimeConstants.MIME_PDF); // 输出到流 OutputStream outputStream = new FileOutputStream(outputFilePath); Docx4J.toFO(foSettings, outputStream, Docx4J.FLAG_EXPORT_PREFER_XSL); outputStream.flush(); outputStream.close(); System.out.println("转换成功!"); } catch (Exception e) { System.err.println("转换失败:" + e.getMessage()); } } } ``` 该示例使用 Docx4J 加载 Word 文档,然后将其转换为 XSL-FO 格式并输出到流中,最后将 XSL-FO 转换为 PDF 格式并将其写入到文件中。请注意,在转换之前,您需要确保已经添加了 docx4j-export-fo 和 Apache FOP 的依赖项。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值