由于java转pdf Aspose需要收费,documents4j是使用本地的MS Office应用做的文件格式转换,Linux没有对应的MS Office应用。这样造成了我们需要选用别的方式进行word的转换。思路:先用freemarker模板工具,生成docx文档,借助libreOffice将docx转pdf。

1、 生成docx模板和xml模板

docx模板:

xml模板:

用zip方式打开docx文档,拷贝word文件下的document.xml充当数据填充模板

2、freemarker填充数据

 引入依赖

        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.30</version>
        </dependency>

 利用document.xml模板写入数据并生成新的含有效数据的xml文件

    public void createWord(ContractVO contractVO) throws Exception {
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_30);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        cfg.setLogTemplateExceptions(false);
        cfg.setWrapUncheckedExceptions(true);
        cfg.setDirectoryForTemplateLoading(new File(filePath));
        Template t =  cfg.getTemplate("document.xml");
        // 导出文件
        FileUtils.createFileDir(filePath + CONTRACT);
        String fileName = contractVO.getCode() + "_" + contractVO.getBabyName() + "_" + "合同";
        File outFile = new File(filePath + CONTRACT + fileName + ".xml");
        try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8))) {
            // 将填充数据填入模板文件并输出到目标文件
            t.process(convertToMap(contractVO), out);
        } catch (Exception e) {
            throw new CommonException("导出合同失败", e);
        }
    }

利用java的zipFile 和 ZipOutputStream 及zipFile.getInputStream() 来根据docx模板导出 (需要把word/document.xml文件替换成(填充完数据[document.xml文件回填])的xml)完成docx文档生成。

package com.icss.sywn.file.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * 其实docx属于zip的一种,这里只需要操作word/document.xml中的数据,其他的数据不用动
 *
 * @author wenbsu
 */
public class XmlToDocx {

    /**
     * @param documentFile 动态生成数据的docunment.xml文件
     * @param docxTemplate docx的模板
     * @param toFilePath   输出文档路径
     */
    public static void outDocx(File documentFile, String docxTemplate, String toFilePath) {
        try {
            File docxFile = new File(docxTemplate);
            ZipFile zipFile = new ZipFile(docxFile);
            Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
            ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(toFilePath));
            int len = -1;
            byte[] buffer = new byte[1024];
            while (zipEntrys.hasMoreElements()) {
                ZipEntry next = zipEntrys.nextElement();
                InputStream is = zipFile.getInputStream(next);
                // 把输入流的文件传到输出流中 如果是word/document.xml由我们输入
                zipout.putNextEntry(new ZipEntry(next.toString()));
                if ("word/document.xml".equals(next.toString())) {
                    InputStream in = new FileInputStream(documentFile);
                    while ((len = in.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    in.close();
                } else {
                    while ((len = is.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    is.close();
                }
            }
            zipout.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3、docx 转 PDF

安装LibreOffice,下载地址:https://www.libreoffice.org/download/download/

引入依赖

<dependency>
  <groupId>org.jodconverter</groupId>
  <artifactId>jodconverter-core</artifactId>
  <version>4.2.0</version>
</dependency>
<dependency>
  <groupId>org.jodconverter</groupId>
  <artifactId>jodconverter-local</artifactId>
  <version>4.2.0</version>
</dependency>
<dependency>
  <groupId>org.jodconverter</groupId>
  <artifactId>jodconverter-spring-boot-starter</artifactId>
  <version>4.2.0</version>
</dependency>
<dependency>
  <groupId>org.libreoffice</groupId>
  <artifactId>ridl</artifactId>
  <version>5.4.2</version>
</dependency>

配置application.yml

jodconverter:
  local:
    enabled: true
    office-home: C:\\Program Files\\LibreOffice
    port-numbers: 2002  

转换pdf

package com.icss.sywn.file.util;

import lombok.extern.slf4j.Slf4j;
import org.jodconverter.DocumentConverter;
import org.jodconverter.document.DefaultDocumentFormatRegistry;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;

@Slf4j
@Component
public class DocumentConverterUtil {

    @Resource
    private DocumentConverter documentConverter;

    public String convert(File in, File out) {

        try {
            long startTime = System.currentTimeMillis();
            documentConverter.convert(in).as(DefaultDocumentFormatRegistry.HTML)
                    .to(out).as(DefaultDocumentFormatRegistry.PDF).execute();
            long conversionTime = System.currentTimeMillis() - startTime;
            log.info(String.format("successful conversion: %s to %s in %dms", in.getName(), "pdf", conversionTime));

        } catch (Exception e) {
            e.printStackTrace();
            return "FAIL";
        }

        return "SUCCESS";
    }
}

完成window环境下生成docx 转 pdf操作,如果是linux环境需要在linux系统安装LibreOffice

操作如下:

1、下载rpm包并解压https://mirrors.cloud.tencent.com/libreoffice/libreoffice/stable/

2、安装

yum install /root/LibreOffice_7.3.1.3_Linux_x86-64_rpm/RPMS/*.rpm

yum install /root/LibreOffice_7.3.1.3_Linux_x86-64_rpm_langpack_zh-CN/RPMS/*.rpm

 3、安装libcairo.so.2依赖库

yum install ibus

4、启动服务

安装路径:/opt/libreoffice7.3
快捷方式:/usr/bin/libreoffice7.3

/usr/bin/libreoffice7.3 --headless --accept="socket,host=127.0.0.1,port=8100;urp;" --nofirststartwizard

5、安装字体

在CentOS7服务器上,利用LibreOffice将word等格式转换为PDF,发现不支持汉字。需要安装字体库。

yum -y install fontconfig

安装完成后,/usr/share目录就可以看到fonts和fontconfig两个目录。

yum -y install ttmkfdir

检查已有字体库

fc-list

复制字体

mkdir /usr/share/fonts/chinese

把docx中用到的字体copy到chinese文件夹里边

修改权限

chmod -R 644 /usr/share/fonts/chinese

汇总生成fonts.scale文件

ttmkfdir /usr/share/fonts/chinese

修改字体配置文件

vim /etc/fonts/fonts.conf

修改的内容如下

<fontconfig>
  ....
  <dir>....
  <dir>/usr/share/fonts/chinese</dir>
  ....
</fontconfig>

更新字体缓存

fc-cache -fv

如果转码出现乱码方格情况,需要把window下docx用到的字体都拷到/opt/libreoffice7.3/share/fonts/truetype目录下,重启服务就可以。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐