一:doc和docx文件

首先我们要了解doc和docx两种word文件的相同点和不同点,为什么ftl可以直接生成doc而生成docx就会报错。

1.doc和docx文件构成

  • 我们可以把doc格式的word文件当成是一个单独的xml文件,而docx当成一个zip压缩包。将一个docx文件的后缀名改成.zip,然后用压缩工具打开,显示的即为docx的目录结构。

2.为什么ftl能直接转成doc而不能直接转成docx

  • ftl生成word文件的过程是通过java选定一个*.ftl模板文件(该ftl模板是通过doc文件另存为xml格式,然后把后缀改为ftl得到),加入map参数集合,调用freemaker组件,生成一个doc格式的word文件。
  • 综合前边概念,我们可以得出结论,freemaker只能通过模板生成一个doc格式的独立文件,而无法得到docx所需要的zip格式,所以ftl无法直接生成docx文件。

3.docx文件格式解析

  • 选一个word文件作为输出模板,然后java代码输出需要提取word压缩包里两个文件:
    1.word路径下的document.xml
    2.word路径下_rels下的document.xml.rels

  • 将docx文件的后缀改为.zip之后,把word路径下的document.xml作为模板,可通过格式化工具把xml文件里的数据格式化,点开后编写word的xml内容,下图以一个段落为例,其他类型请自行参考openxml语法或自己在word中对应

  • 编写完xml模板之后,进入代码开发阶段,
    1.同ftl生成doc一样,第一步要先封装数据到一个map中
    2.指定输出docx的文件路径
    3.指定两个从word压缩包中提取的文件路径
    4.执行输出
    代码示例如下:

 //封装数据Map<String,Object> dataMap=new HashMap<>();dataMap.put("title","示例");//key名对应xml模板里的freemaker标签//输出docx的模板String originalTemplate = tempPath+ File.separator+"needsOriginalTemplate.docx";//word中提取的两个文件,代码中可以根据实际情况更改名字String documentXmlRels = "document.xml.rels";String document = "document.xml";//执行输出Xml2DocxUtil.Xml2Docx(outFile,dataMap,document,documentXmlRels,originalTemplate);

下方附上 Xml2DocxUtil.java 以及FreeMarkUtils.java

Xml2DocxUtil.java


import cn.hutool.core.io.FileUtil;import java.io.*;import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;public class Xml2DocxUtil {/**** @param outFile 输出文件* @param dataMap 数据* @param document 模板文件* @param documentXmlRels 模板关联文件* @param originalTemplate 模板原始docx文件* @return retMap succ 是否成功 true & false ; msg返回异常信息*/public static Map<String,Object> Xml2Docx(File outFile, Map<String,Object> dataMap, String document, String documentXmlRels, String originalTemplate){Map<String,Object> retMap = new HashMap<>();retMap.put("succ",true);ZipOutputStream zipout = null;OutputStream outputStream = FileUtil.getOutputStream(outFile);try {//图片配置文件模板ByteArrayInputStream documentXmlRelsInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, documentXmlRels);//内容模板ByteArrayInputStream documentInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, document);ZipFile zipFile = new ZipFile(originalTemplate);Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();zipout = new ZipOutputStream(outputStream);//开始覆盖文档------------------int len = -1;byte[] buffer = new byte[1024];while (zipEntrys.hasMoreElements()) {ZipEntry next = zipEntrys.nextElement();InputStream is = zipFile.getInputStream(next);if (next.toString().indexOf("media") < 0) {zipout.putNextEntry(new ZipEntry(next.getName()));if (next.getName().indexOf("document.xml.rels") > 0) { //如果是document.xml.rels由我们输入if (documentXmlRelsInput != null) {while ((len = documentXmlRelsInput.read(buffer)) != -1) {zipout.write(buffer, 0, len);}documentXmlRelsInput.close();}} else if ("word/document.xml".equals(next.getName())) {//如果是word/document.xml由我们输入if (documentInput != null) {while ((len = documentInput.read(buffer)) != -1) {zipout.write(buffer, 0, len);}documentInput.close();}} else {while ((len = is.read(buffer)) != -1) {zipout.write(buffer, 0, len);}is.close();}}}} catch (Exception e) {e.getStackTrace();retMap.put("succ",false);retMap.put("msg",e.getMessage());}finally {if(zipout!=null){try {zipout.close();} catch (IOException e) {e.getStackTrace();retMap.put("succ",false);retMap.put("msg",e.getMessage());}}if(outputStream!=null){try {outputStream.close();} catch (IOException e) {e.getStackTrace();retMap.put("succ",false);retMap.put("msg",e.getMessage());}}}return retMap;}
}

FreeMarkUtils.java


import freemarker.template.Configuration;
import freemarker.template.Template;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;import java.util.Map;public class FreeMarkUtils {private static Logger logger = LoggerFactory.getLogger(FreeMarkUtils.class);public static Configuration getConfiguration(){//创建配置实例Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);//设置编码configuration.setDefaultEncoding("utf-8");configuration.setClassForTemplateLoading(FreeMarkUtils.class, "/templates/needsFileTemplates/");return configuration;}/*** 获取模板字符串输入流* @param dataMap   参数* @param templateName  模板名称* @return*/public static ByteArrayInputStream getFreemarkerContentInputStream(Map dataMap, String templateName) {ByteArrayInputStream in = null;try {//获取模板Template template = getConfiguration().getTemplate(templateName);StringWriter swriter = new StringWriter();//生成文件template.process(dataMap, swriter);in = new ByteArrayInputStream(swriter.toString().getBytes(StandardCharsets.UTF_8));//这里一定要设置utf-8编码 否则导出的word中中文会是乱码} catch (Exception e) {e.printStackTrace();logger.error("模板生成错误!");}return in;}
}

欢迎大家评论区进行交流,之后会发表一篇如何通过java在docx的word文件中插入一个docx格式的word文件的文章。

Java通过Freemarker生成docx文件相关推荐

  1. Java使用freemarker生成word文件

    首先声明我的项目是一个web项目,生成的word文件直接通过response响应发送给前端.如果不是web项目的话可以像网上的其他教程一样将生成的word保存在本地. 要利用freemarker生成w ...

  2. Java通过freemarker生成pdf文件并盖章

    Java代码生成pdf回执文件,直接上代码: package com.pdf;import java.io.BufferedWriter; import java.io.File; import ja ...

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

    Java使用freemarker生成word文档后转pdf 先来看看效果图 进入正题 项目需求: 为订单后生成对应的pdf文档,文档内包含图片. 方案一:使用freemarker和itext把html ...

  4. HTML生成PDF模板(Java iText+FreeMarker生成PDF(HTML转PDF))

    Java iText+FreeMarker生成PDF(HTML转PDF) 1.背景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中转账的电子回单,签约的电子合同等.方便用户查看,下载,打 ...

  5. 若依 springboot 使用freemarker生成word文件,并导出下载

    目录 freemarker生成word文件并导出 一.环境准备 二.编写代码 1.实体类 2.mapper.xml文件 3.mapper.java文件 4.Service.java 5.Service ...

  6. eclipse编译java项目class文件_动态编译 Java 代码以及生成 Jar 文件

    导读: 最近在看 Flink 源码的时候发现到一段实用的代码,该代码实现了 java 动态编译以及生成 jar 文件.将其进行改进后可以应用到我们的平台上,实现在平台页面上编写 java 代码语句,提 ...

  7. JAVA 根据模板生成doc文件

    JAVA 根据模板生成doc文件 需求 根据模板生成对应的doc文档,文档内容动态填充. 实现 1.将doc模板转换为ftl文件,放入项目中 1.1 首先将模板另存为xml文件 1.2 更改xml文件 ...

  8. java使用poi生成Excel文件并合并单元格

    java使用poi生成Excel文件并合并单元格        业务需要根据 分管部门 字段进行合并,现在提供一种思路. controller层 @Inject(target = "/inf ...

  9. Freemarker生成word文件,打开后页眉和页脚图片不显示

    Freemarker生成word文件,打开后页眉和页脚图片不显示 在我们开发过程中通常会把模板文件Ctrl+Alt+L格式化,方便处理.这样就造成word的标签格式产生多余的换行或者空白,但是word ...

最新文章

  1. 安装旧版本插件_iOS 应用降级插件,支持任意版本升降
  2. 【定时任务】quartz表达式Cron Expression解析
  3. 云计算相关资料/博客/网上收集的关于OpenStack的一些资源
  4. Grafana Prometheus 服务安装部署(Linux服务器监控)
  5. 计算机有什么著名基金经理排名,百万年薪的基金经理,都是什么专业出身?!...
  6. hdoj--5621--KK's Point(简单数学)
  7. Install-Package Ninject -Project SportsStore.WebUI
  8. goods购物表MySQL的代码_python采用sqlachmy购物商城
  9. 移动端适配的理解——REM方案
  10. Python机器学习经典实例
  11. Linux 线程———详解
  12. baymax平台导入任务错误日志报错: Please login with USER and PASS.
  13. 12月大学计算机二级考试时间,2020年12月计算机二级考试报名时间及考试安排
  14. 用python还需要stata吗_极冷知识点——Stata/Python/R自带数据导入(附代码)
  15. OTA 差分升级包的制作
  16. alertmanager集群搭建
  17. 中国航空公司特点机型
  18. 计划的主体部分应有哪些内容_计划主体部分包含哪些内容
  19. 信号系统一些基本概念
  20. VMware CentOS6.5 安装VMware Tools

热门文章

  1. 数显倾角传感器的应用
  2. php账单明细功能怎么实现,php 账单生成
  3. iOS 修改键盘的return键
  4. 金盾防火墙为你保驾护航
  5. 番外7林芝·救赎之旅的最后一站·中——AI主题科幻小说《地与光》
  6. O-2-1 赚钱宝安装entware
  7. 产品管理之创新商业模式
  8. WordPress主题:仿虾米音乐CMS模板
  9. 塔图姆单节独得15分 凯尔特人126:94大胜黄蜂
  10. Windows 8操作系统犹抱琵琶半遮面