根据模板动态生成word文件

需求:

用freemarker根据doc模板生成word文件并转化为pdf文件
  1. 准备模板文件
    在这里插入图片描述
  2. 将模板文件另存为xml文件
    在这里插入图片描述
  3. xml内容格式化后用文本编辑器打开
  4. 用el表达式替换其中要动态填写的数据,并将后缀改为ftl
    在这里插入图片描述
    模板已经准备好了
  5. (spring boot)开始导入maven坐标
		<dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.3</version>
        </dependency>

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

        <dependency>
            <groupId>org.docx4j</groupId>
            <artifactId>docx4j</artifactId>
            <version>6.1.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.docx4j/docx4j-export-fo -->
        <dependency>
            <groupId>org.docx4j</groupId>
            <artifactId>docx4j-export-fo</artifactId>
            <version>6.0.1</version>
        </dependency>
  1. 封装好的工具类
package com.cicro.exa.utils;

import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.docx4j.Docx4J;
import org.docx4j.convert.out.FOSettings;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.springframework.core.io.ClassPathResource;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class PdfUtil {
   private static String separator = File.separator;//文件夹路径分格符

   private static Configuration configuration =null;

   private static final String DOC_SUFFIX=".doc";

   private static final String PDF_SUFFIX=".pdf";
   static {
       //创建配置实例
       configuration=new Configuration(Configuration.getVersion());

       //设置编码
       configuration.setDefaultEncoding("UTF-8");
   }

   //=========================================生成申请表pdf===================================



   /**
    * word(docx)转pdf
    * @param wordPath  docx文件路径
    * @param pdfPath  pdf文件路径
    * @return  生成的带水印的pdf路径
    */
   public static String convertDocx2Pdf(String wordPath,String pdfPath) {
       OutputStream os = null;
       InputStream is = null;
       try {
           is = new FileInputStream(new File(wordPath));
           WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is);
           Mapper fontMapper = new IdentityPlusMapper();
           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"));

           mlPackage.setFontMapper(fontMapper);

           //输出pdf文件路径和名称
           String pdfName = wordPath.substring(0, wordPath.lastIndexOf("."));
           pdfName = pdfName.substring(pdfName.lastIndexOf("\\") + 1);
           String pdfOutPath = pdfPath + pdfName + PDF_SUFFIX;

           File file=new File(pdfOutPath);
           if (!file.getParentFile().exists()){
               FileUtils.forceMkdir(file.getParentFile());
           }
          // String pdfNoMarkPath = System.getProperty("java.io.tmpdir").replaceAll(separator + "$", "") + separator + fileName;

           os = new java.io.FileOutputStream(pdfOutPath);

           //docx4j  docx转pdf
           FOSettings foSettings = Docx4J.createFOSettings();
           foSettings.setWmlPackage(mlPackage);
           Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);

           is.close();//关闭输入流
           os.close();//关闭输出流
           return pdfOutPath;
           //添加水印
           //return addTextMark(pdfOutPath);
       } catch (Exception e) {
           e.printStackTrace();
           try {
               if(is != null){
                   is.close();
               }
               if(os != null){
                   os.close();
               }
           }catch (Exception ex){
               ex.printStackTrace();
           }
       }finally {
           File file = new File(wordPath);
           if(file!=null&&file.isFile()&&file.exists()){
               file.delete();
           }
       }
       return "";
   }

   /**
    * 添加水印图片
    * @param inPdfPath 无水印pdf路径
    * @return 生成的带水印的pdf路径
    */
   private static String addTextMark(String inPdfPath) {
       PdfStamper stamp = null;
       PdfReader reader = null;
       try {
           //输出pdf带水印文件路径和名称
           String fileName = "pdfMark_" + System.currentTimeMillis() + ".pdf";
           String outPdfMarkPath = System.getProperty("java.io.tmpdir").replaceAll(separator + "$", "") + separator + fileName;

           //添加水印
           reader = new PdfReader(inPdfPath, "PDF".getBytes());
           stamp = new PdfStamper(reader, new FileOutputStream(new File(outPdfMarkPath)));
           PdfContentByte under;
           int pageSize = reader.getNumberOfPages();// 原pdf文件的总页数
           //水印图片
           ClassPathResource resource = new ClassPathResource("template" +  File.separator + "mark.png");
           File file = resource.getFile();
           Image image = Image.getInstance(file.getPath());
           for (int i = 1; i <= pageSize; i++) {
               under = stamp.getUnderContent(i);// 水印在之前文本下
               image.setAbsolutePosition(100, 210);//水印位置
               under.addImage(image);
           }
           stamp.close();// 关闭
           reader.close();//关闭

           return outPdfMarkPath;
       } catch (Exception e) {
           e.printStackTrace();
           try {
               if (stamp != null) {
                   stamp.close();
               }
               if (reader != null) {
                   reader.close();//关闭
               }
           } catch (Exception ex) {
               ex.printStackTrace();
           }
       } finally {
           //删除生成的无水印pdf
           File file = new File(inPdfPath);
           if (file != null && file.exists() && file.isFile()) {
               file.delete();
           }
       }
       return "";
   }

   /**
    *
    * @param dataMap 模板数据内容 (map中封装的数据要与模板中的参数名称一一对应)
    * @param tempPath  模板路径
    * @param outFilePath  输出路径
    * @param tempName 模板名称
    * @return 生成的doc文档存放路径
    */
 public static String  createDoc(Map<String, String> dataMap, String tempPath, String outFilePath, String tempName) throws IOException {

     if (!new File(tempPath).getParentFile().exists()){
         FileUtils.forceMkdir(new File(tempPath).getParentFile());
     }
     //设置模板文件路径
     configuration.setDirectoryForTemplateLoading(new File(tempPath));

     //设置模板名称
     Template template = configuration.getTemplate(tempName);

     //输出文档路径及名称
     File outFile = new File(outFilePath+separator+dataMap.get("ysqId")+DOC_SUFFIX);
     if (!outFile.getParentFile().exists()){
         FileUtils.forceMkdir(outFile.getParentFile());
     }

     Writer writer=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"utf-8"));

     try {
         template.process(dataMap,writer);
     } catch (TemplateException e) {
         log.info("word文档{}生成错误",dataMap.get("id"));
         e.printStackTrace();
     }finally {
         writer.close();
     }
     log.info("word文件路径:{}",outFile.getPath());
     return outFile.getPath();
 }

   public static void main(String[] args) throws IOException {
     String tempPath="H:/Java_project/conversion/src/main/resources/";
     String outFilePath="D:/downLoad";
     String tempName="ysqgk.ftl";
     Map dataMap=new HashMap();
     dataMap.put("id","123");
     dataMap.put("name","测试名称");
     dataMap.put("company","测试公司");
     dataMap.put("cardName","测试证件");
     dataMap.put("cardCode","测试账号");
       String doc = createDoc(dataMap, tempPath, outFilePath, tempName);

       String pdf = convertDocx2Pdf(doc, "D:/PDF/");

       System.out.println(doc);
       System.out.println(pdf);
   }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值