Java使用freemarker生成word文档并转pdf文档

发布于:2023-04-27 ⋅ 阅读:(2021) ⋅ 点赞:(1)

Java使用freemarker生成word文档后转pdf


项目需求: 为订单后生成对应的pdf文档,文档内包含图片。
方案一:使用freemarker和itext把html转pdf,存在中文乱码,宋体不识别,需下载simsun.ttc字体,空白占位符不识别等等问题,对前端依赖性较大,不推荐;
方案二:freemarker生成word文档后通过微软提供的openoffice工具转pdf文档;
方案三: freemarker生成word文档后通过aspose.words转pdf文档,该方式不需要安装插件,只需导入对应jar包就好,但生成pdf存在水印,需要进行破解;(aspose.words需要付费的哦,用于商业请授权购买正版)
方案四:python用pdfkit生成pdf,各位有时间自己研究吧;

先来看看效果图

在这里插入图片描述

进入正题

1.生成pdf文档流程
1):准备一个word表格,然后另存为xml格式的文件;
2):为了便于观看文档结构和编辑代码,对xml文件进行格式化(在线格式化网址);
3):把xml文件的后缀名改为ftl,使用freemarker表达式进行数据的动态添加(模板中图片是以base64编码展示的,替换成自己的图片编码);
4):导入相关jar包;
5):通过freemarker模板引擎技术把ftl模板文件转为word文档;
6):通过aspose.words把word文档转为pdf文档,至此完成;

2.相关jar包准备

    <!--freemarker jar-->
    <dependency>
      <groupId>org.freemarker</groupId>
      <artifactId>freemarker</artifactId>
      <version>2.3.22</version>
    </dependency>
    
    <!--二维码操作jar-->
    <dependency>
      <groupId>com.google.zxing</groupId>
      <artifactId>javase</artifactId>
      <version>3.0.0</version>
    </dependency>
	<!-- https://mvnrepository.com/artifact/com.aspose/aspose-words -->
	<dependency>
	    <groupId>com.aspose</groupId>
	    <artifactId>aspose-words</artifactId>
	    <version>14.7.0</version>
	</dependency>

因为我们用的破解版,所以请点击此处下载我给各位准备的aspose-words.jar和ftl模板( 提取码: jrs5)

2.开始我们的代码

文档生成工具类Xml2Word2Pdf.java

import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Encoder;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

/**
 * @Author: zzr-zhangs
 * @Date: 2020-01-14 13:12
 * @Content: xml->word->pdf (通过freemarker把通过word生成的xml模板动态添加数据并生成word文档,通过aspose.words把word文档转为pdf文档)
 * @Description: aspose.words需付费购买,目前使用破解版,需要引入freemarker的jar和aspose-words-jdk16-16.4.0.jar
 */
public class Xml2Word2Pdf {

    private static Configuration configuration = null;

    /**
     * 初始化配置并设置默认编码UTF-8
     */
    static {
        configuration = new Configuration();
        configuration.setDefaultEncoding("UTF-8");
    }

    /**
     * 通过模板文件创建word文档(模板文件的格式可到网站进行在线格式化,网址推荐:https://tool.oschina.net/codeformat/xml/)
     *
     * @param tpmplateFilePath 模板文件路径(完整路径,不包含文件如:D:/templates)
     * @param tpmplateFileName 模板文件名称
     * @param outFilePath      输出文件路径(完整路径,包含文件名称 如:D:/templates/order.doc)
     * @param dataMap          需要动态添加的数据
     */
    public static void createWord(String tpmplateFilePath, String tpmplateFileName, String outFilePath, Map<String, Object> dataMap) {
        try {
            //如果不传模板文件路径就默认取resources下的templates文件夹中的模板文件
            if (StringUtils.isEmpty(tpmplateFilePath)) {
                configuration.setClassForTemplateLoading(Xml2Word2Pdf.class, "/templates");
            } else {
                configuration.setDirectoryForTemplateLoading(new File(tpmplateFilePath)); // XML文件所存在的位置
            }
            //获取文档XML模板
            Template template = configuration.getTemplate(tpmplateFileName);
            //设置输出文件位置和文件名
            File outFile = new File(outFilePath);
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
            template.process(dataMap, out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description: 验证aspose.word组件是否授权:无授权的文件有水印标记
     */
    public static boolean getLicense() {
        boolean result = false;
        try {
            String s = "<License><Data><Products><Product>Aspose.Total for Java</Product><Product>Aspose.Words for Java</Product></Products><EditionType>Enterprise</EditionType><SubscriptionExpiry>20991231</SubscriptionExpiry><LicenseExpiry>20991231</LicenseExpiry><SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber></Data><Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature></License>";
            ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes());
            //InputStream inputStream = Xml2Word2Pdf.class.getClassLoader().getResourceAsStream("\\license.xml");
            com.aspose.words.License license = new com.aspose.words.License();
            license.setLicense(inputStream);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 使用aspose.word把word文档转为pdf文档
     *
     * @param sourceFile word文档绝对路径(如:D:/templates/order.doc)
     * @param destFile   pdf文档绝对路径(如:D:/templates/order.pdf)
     */
    public static String word2Pdf(String sourceFile, String destFile) throws Exception {
        destFile = StringUtils.isEmpty(destFile) ? sourceFile.replace(".doc", ".pdf") : destFile;
        // 验证License 若不验证则转化出的pdf文档会有水印产生
        if (!getLicense()) {
            throw new Exception("生成PDF文档,验证License失败!");
        }
        try {
            File file = new File(destFile);  //新建一个空白pdf文档
            FileOutputStream os = new FileOutputStream(file);
            Document doc = new Document(sourceFile);//通过sourceFile创建word文档对象
            doc.save(os, SaveFormat.PDF);
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("生成PDF文档失败!");
        }
        return destFile;
    }

    /**
     * 图片转base64编码
     *
     * @param imgFilePath 图片路径
     * @return 返回base64编码字符串
     */
    public static String ima2Base64(String imgFilePath) {
        InputStream in = null;
        byte[] data = null;
        try {
            in = new FileInputStream(imgFilePath);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }

    /**
     * 简单的测试
     *
     * @remark 需要在D盘创建templates文件夹并准备相应的的xml和图片
     */
    public static void main(String[] args) throws Exception {
        long start = System.currentTimeMillis();
        //1.基础数据定义
        String templatePath = "D:/templates/";//模板路径/生成文档存放路径
        String sourceFile = templatePath+"order.doc";//生成的word文档路径和名称
        String templateName = "word_2003.ftl";//模板名称
        String sealImgPath = "D:/templates/liangzai.png";//盖章图片路径
        String nameImgPath = "D:/templates/zhangjie.jpg";//名字图片路径
        //2. dataMap的赋值
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("orderNo", "ZRP202001150004");
        dataMap.put("sealImgBase64", ima2Base64(sealImgPath));
        dataMap.put("nameImgBase64", ima2Base64(nameImgPath));
        //生成word文档
        createWord(templatePath, templateName, sourceFile, dataMap);
        //word文档转pdf文档
        word2Pdf(sourceFile, null);
        long end = System.currentTimeMillis();
        System.out.println("文档生成耗时:" + ((end - start) / 1000.0) + "秒"); 
    }
}

参考博客:https://blog.csdn.net/qq_41507845/article/details/90518846