admin管理员组

文章数量:1605153

Word转Pdf

起因

公司原先的需求是有个证书下载,甲方提供了一个docx格式的word模版,我们这边就设计证书下载的格式为docx。在完成之后业务那边要求将下载格式改为pdf格式,考虑过直接使用itext-pdf按照word模版直接输出成pdf文件,但因为功能已经完成,使用itext-pdf就相当于重新作功能,就考虑将word转pdf。

解决方法

首先在网上找到的一个aspose-words-15.8.0-jdk16的jar包很好用,可惜是收费的,于是只得另寻方法。还有利用itext-pdf将word先转为html再将html转为pdf文件的。还有一些其他方法,比如使用docx4j,spireDoc,xdocreport,但是有些方法只适用于windows平台,有兴趣的可以尝试一下。

最后方案

使用xdocreport将docx格式文件转为pdf。

先放依赖

<dependency>
  <groupId>fr.opensagres.xdocreport</groupId>
  <artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
  <version>1.0.6</version>
</dependency>

先搞个main方法测试一下

public void wordToPdf(String wordPath,String pdfPath)  {
  InputStream in = null;
  OutputStream outPDF = null;
  XWPFDocument document = null;
  try{
    in = new FileInputStream(wordPath);
    document = new XWPFDocument(in);
    // 将word转成pdf
    PdfOptions options = PdfOptions.create();
    outPDF = new FileOutputStream(pdfPath);
    options.fontProvider(new IFontProvider() {
      @Override
      public Font getFont(String familyName, String encoding, float size, int style, java.awt.Color color) {
        try {
          String prefixFont = null;
          String os = System.getProperties().getProperty("os.name");
          if (os.startsWith("win") || os.startsWith("Win")) {
            /*windows字体*/
            prefixFont = "C:\\Windows\\Fonts\\simsun.ttc,0";
          } else {
            /*linux字体*/
            prefixFont = "/Users/zhaochunhui/Fonts/Fonts/simsun.ttc,0";
          }
          BaseFont stChinese = BaseFont.createFont(prefixFont, BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
          BaseFont fsChinese = BaseFont.createFont("/Users/zhaochunhui/Fonts/Fonts/simfang.ttf",
                                                   BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
          Font stFontChinese = new Font(stChinese, size, style, color);
          Font fsFontChinese = new Font(fsChinese, size, style, color);
          if (familyName != null){
            if ("仿宋".equals(familyName)){
              fsFontChinese.setFamily(familyName);
              return fsFontChinese;
            }else{
              stFontChinese.setFamily(familyName);
            }
          }
          return stFontChinese;
        } catch (Exception e) {
          e.printStackTrace();
          return null;
        }
      }
    });
    PdfConverter.getInstance().convert(document, outPDF, options);
  }catch (IOException e){
    e.printStackTrace();
  }finally {
    try {
      if (in != null) in.close();
      if (outPDF != null) outPDF.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

写个main方法测试:

public static void main(String[] args) throws Exception {
  String filePath = "/Users/zhaochunhui/test/test.docx";
  String outPath = "/Users/zhaochunhui/test/a.pdf";
  WordPdfUtils wordPdfUtils = new WordPdfUtils();
  wordPdfUtils.wordToPdf(filePath,outPath);
}

测试结果:

这是原先的docx文件:

这是转完的pdf文件:

word转pdf的字体问题

options.fontProvider(IFontProvider fontProvider)方法需要一个IFontProvider,而这个IFontProvider需要我们自己去实现,主要需要我们去重写getFont方法,我们其实主要需要做的就是根据getFont方法中的familyName(这个参数其实就是字体名称)参数去返回具体的Font对象,如果options.fontProvider(IFontProvider fontProvider)这个方法不写的话转换后的pdf文档中文字体将无法显示。

关于在getFont方法中如何返回具体的Font: 可以使用BaseFont.createFont()先创建多个BaseFont对象,再通过new Font()方法得到多个Font对象,然后再根据familyName返回具体的Font。这边的BaseFont.createFont()方法中第一个参数可以传字体文件位置,基本上字体文件为ttc文件或ttf文件,需要注意的是是如果是ttc文件需要在字符串中添加",0",否则会报错。关于ttc和ttf的区别,ttc可以包含一种以上字体,而ttf只能有一种字体。

如何知道一个ttc文件或者ttf文件包含哪些字体?

在mac上我是直接双击字体文件,根据弹窗提示安装某某字体得知

如图是点击simsun.ttc文件后的弹窗,可以知道simsun.ttc文件里面放的是宋体和新宋体两种字体,windows应该也可以进行相似的操作。理论上如果需要转换后的pdf文件字体和word上字体一样,原先word上用到几个字体我们就需要把这些字体文件全部拿过来。然后在getFont方法中根据familyName返回相应的Font对象,我这边getFont方法可以考虑用map再优化下,但是先这样吧。

我这边的字体文件是从windows上copy过来的,windows上字体文件具体路径:C:\Windows\Fonts

参考链接:(32条消息) xdocreport根据模板生成合同(docx/pdf)神器:(二)如何在spring boot中集成_热水钟博客-CSDN博客_fr.opensagres.xdocreport

https://blog.csdn/hxxjxw/article/details/104480148

POI 实现 word转成pdf - 挽留匆匆的美丽 - 博客园 (cnblogs)

另附一篇另外一种测试成功的别人的博客:
https://blog.csdn/WoodYangOY/article/details/109902581
需要注意的是这个方法需要在运行的机器上事先将需要的字体都安装上

本文标签: wordPDF