java生成docx_java利用Freemarker模板生成docx格式的word文档
之前写过一篇利用Freemarker模板生成doc的博客,不过那个博客有点缺陷,生成的word占用的空间很大,几百页的word有将近100M了。所以,后面需求必须是生成的docx文档,结果导出后正常才几M,昨天花了一天的时间实现。
具体思路
1.把docx文档修改为ZIP格式(修改.docx后缀名为.zip)
2.获取zip里的document.xml文档以及_rels文件夹下的document.xml.rels文档
3.把内容填充到document.xml里,以及图片配置信息填充至document.xml.rels文档里
4.在输入docx文档的时候把填充过内容的的 document.xml、document.xml.rels用流的方式写入zip(详见下面代码)。
5.把图片写入zip文件下word/media文件夹中
6.输出docx文档
docx模板修改成zip格式后的信息如下(因为word文档本身就是ZIP格式实现的)
document.xml里存放主要数据
media存放图片信息
_rels里存放配置信息
注意:如果docx模板里的图片带有具体路径的话,则图片的格式不受限制。
如果docx模板里里图片信息不带路径,则模板仅支持和模板图片类型一致的图片。
处理流程
1.准备好docx模板
2.把docx文档修改为ZIP格式(修改.docx后缀名为.zip)
3.获取zip文件里的word文件夹下的document.xml以及_rels文件夹里的document.xml.rels文件作为模板。
注意:这里图片配置信息是根据 rId来获取的,为了避免重复,可以根据自己具体的业务规则来实现
4.填充模板信息、写入图片信息。
//outputStream 输出流可以自己定义 浏览器或者文件输出流
public static void createDocx(Map dataMap,OutputStream outputStream) {
ZipOutputStream zipout = null;
try {
//图片配置文件模板
ByteArrayInputStream documentXmlRelsInput =FreeMarkUtils.getFreemarkerContentInputStream(dataMap, documentXmlRels);
//内容模板
ByteArrayInputStream documentInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, document);
//最初设计的模板
File docxFile = new File(WordUtils.class.getClassLoader().getResource(template).getPath());
if (!docxFile.exists()) {
docxFile.createNewFile();
}
ZipFile zipFile = new ZipFile(docxFile);
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();
}
}
}
//写入图片
List> picList = (List>) dataMap.get("picList");
for (Map pic : picList) {
ZipEntry next = new ZipEntry("word" + separator + "media" + separator + pic.get("name"));
zipout.putNextEntry(new ZipEntry(next.toString()));
InputStream in = (ByteArrayInputStream)pic.get("code");
while ((len = in.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
in.close();
}
} catch (Exception e) {
logger.error("word导出失败:"+e.getStackTrace());
}finally {
if(zipout!=null){
try {
zipout.close();
} catch (IOException e) {
logger.error("io异常");
}
}
if(outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
logger.error("io异常");
}
}
}
}
/**
* 获取freemarker模板字符串
* @author lpf
*/
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, "/template");
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("utf-8"));//这里一定要设置utf-8编码 否则导出的word中中文会是乱码
} catch (Exception e) {
logger.error("模板生成错误!");
}
return in;
}
}
5.输出word测试
就是这么简单,比较麻烦的就是如果word比较复杂的话写freemarkr标签要仔细一些,还有word中的字符尽量对特殊字符有转义,否则会引起word打不开的现象。
总结
这里最重要的一个思想是把文件输出到ByteArrayOutputStream里,下载的时候把这个字节写出就行了。开发的时候注意编码问题,用这种方式导出还有一个好处就是,你会发现,同样一个word。导出doc格式的文件大小要比docx格式的文件大小大的多,所以还是推荐用这种;
java生成docx_java利用Freemarker模板生成docx格式的word文档相关推荐
- java利用Freemarker模板生成docx格式的word文档(全过程)
参考汇总: wordexport: JAVA生成并导出Word文档技术论证 java利用Freemarker模板生成docx格式的word文档(全过程) - 旁光 - 博客园 # 参考资料 - 其他项 ...
- springboot结合Freemarker模板生成docx格式的word文档(附代码)
首先参考的是这篇文章: java利用Freemarker模板生成docx格式的word文档(全过程) - 旁光 - 博客园参考:https://my.oschina.net/u/3737136/blo ...
- Django在线预览docx格式的word文档
Django在线预览docx格式的word文档 第一步 明确功能是:预览word的docx文件. 具体实现是:在Django的模板文件中,定义预览方法:read_word2html from pydo ...
- java利用Freemarker模板生成格式友好的doc或者docx文档
之前写过一篇利用Freemarker模板生成doc的博客,不过那个博客有点缺陷,不支持生成docx格式的文档.所以,这里补充一篇,生成docx或doc格式的文档以具体的docx模板或者doc模板为主. ...
- 利用Freemarker模板生成doc或者docx文档(转载整理)
可以直接看主要代码实现 doc作为模板文件生成指定格式的doc文件 实现逻辑 1.把作为模板的doc文件另存为xml文件 2.凡是需要填充的数据用${xxxx}替代 3.利用Template类将数据填 ...
- freemarker 生成java_半自动化Java代码生成器[利用freemarker模板生成]
rapid-generator 半自动化Java代码生成器[利用freemarker模板生成] 增加一些定制和扩展, 修改为基于MAVEN的格式. 整体架构保持不变. 增加的特性为: 支持表名前缀去除 ...
- Java项目中利用Freemarker模板引擎导出--生成Word文档
应邀写的一篇文章:Java项目中利用Freemarker模板引擎导出--生成Word文档 资源下载:https://download.csdn.net/download/weixin_41367523 ...
- 利用 freemarker 模板生成 word 小结
在企业级开发时,不可避免的会遇到生成 word 文档的需求,有两种常用的方案,1.使用 Apache POI 在后台通过代码生成 word 文档:2.使用模板生成 word 文档.第二种方法比较简单, ...
- Java 将xml模板动态填充数据转换为word文档
需要用到的jar包: commons-codec-1.10.jar freemarker-2.3.21.jar jacob-1.6.jar 实现思路: 1.先将word文档另存为 : Word 200 ...
最新文章
- CloudStack 4.2 与CloudStack 4.1二级存储API发生变化
- nginx-1.13.x源码安装
- 运维小姐姐说这篇Consul集群和ACL配置超给力(保姆级)
- php 点对点,浅析点对点(End-to-End)的场景文字识别
- python中带附件发送电子邮件_python发送带附件邮件
- 中小企业集群ntpd服务搭建
- subversion的windows平台下载地址
- PHP的静态变量和引用函数
- 在html5水平边距属性hspace,HTML5 常用语法一览(列举不支持的属性)
- Capture One使用的几个小技巧
- 系统架构师论文-图书馆网络应用体系安全设计
- 关于Open函数的newline参数
- 厦大C语言上机 1413 模式匹配
- Python爬虫实战—vmgrils图片网站
- linux p4 环境配置,linux p4使用心得
- 给计算机老师的元旦祝福,送给老师的元旦祝福语
- 基于Nonebot2搭建QQ机器人(一)机器人环境配置
- 计算机会议期刊投稿,中国计算机学会推荐的投稿期刊和会议
- 系统特征根_20160204
- mysql 查询不重复的值_在 MySQL 中查询不重复记录值的方法
热门文章
- 电脑还原数据丢失的解决技巧
- HQChart使用教程2- 如何把自定义指标显示在K线图页面
- 小红书爆款标题怎么写?分享你一份爆款标题公式。
- HTML批量删除标记,批量删除LabelImg制作的.xml中的部分标签值(删除.xml的节点值)...
- golang量化投资数据接口是什么
- 山重水复疑无路,最快下降问梯度
- 基于STM32单片机温湿度一氧化碳(CO)浓度仿真设计
- 解决Win11安装PS2022版本卡顿闪退问题 win11安装Photoshop2022闪退卡顿问题解决方案
- 自动化测试之ios测试脚本
- 端口开通情况检测工具的阿里云服务器