这是写的另一个导出word方法:https://www.cnblogs.com/pxblog/p/13072711.html

引入jar包,freemarker.jar、apache-ant-zip-1.8.0.jar(制作压缩包使用)

下载地址:   https://yvioo.lanzous.com/b00njhxoh   密码:2mcs

或者maven

<!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.ant/ant -->
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.8.0</version>
</dependency>

1、准备ftl模板,先在一个word中模板排版好,然后另存为-保存成“Word 2003 XML文档” 后缀名是.xml的文件

注:模板中的值要使用占位符进行填充 ,如下图所示,“name”名称是根据后台代码来的,这里可以换成自己的

然后生成.xml文件后,可以利用网上格式化工具格式化看下 生成的模板文件是否正确,占位符“${name}”必须是完整的,中间不能含有其他字符

如果word模板中含有图片,图片在xml文件中展现的形式是Base64格式的 ,包含在<w:binData>和</w:binData>中,把Base64删掉,替换成占位符,我这里使用的是“${photo}”(<w:binData>和</w:binData>中除了占位符不能有其他代码,也不能换行,主要是下面两个标签内都不能有其他标签)

如果没有<w:binData>和</w:binData>标签的话,就是在模板中没有把图片放进去,需要把图片也放进去模板中,然后生成xml文件

<w:binData w:name="wordml://03000001.png" xml:space="preserve">${photo}</w:binData>
<v:shape id="图片 2" o:spid="_x0000_i1025" type="#_x0000_t75" style="width:56.5pt;height:93pt;visibility:visible;mso-wrap-style:square"><v:imagedata src="wordml://03000001.png" o:title="touxiangm"/></v:shape>

如果是多张图片的时候,就在模板文档里面放多张图片,然后看生成的模板样子,内容都是可以循环的,把共同部分拿出来,然后使用<#list>标签进行循环遍历,有些字段循环也是不一样,如下图所示,每个人可能模板不一样。

2、然后把保存的wordExport.xml文件 后缀名改成.ftl文件

3、后台代码

导出word工具类

WordUtils.javapackage testword;
import java.io.*;
import java.util.Map; import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import freemarker.template.Configuration;
import freemarker.template.Template;
import sun.misc.BASE64Encoder; public class WordUtils {
//配置信息,代码本身写的还是很可读的,就不过多注解了
private static Configuration configuration = null;
//这里注意的是利用WordUtils的类加载器动态获得模板文件的位置
// private static final String templateFolder = WordUtils.class.getClassLoader().getResource("../../").getPath() + "WEB-INF/templetes/"; public File exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map,String title,String templateFolder,String toDirFloder) throws IOException {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8"); //模板所在文件夹
configuration.setDirectoryForTemplateLoading(new File(templateFolder));
//wordExport.ftl为模板文件名称
Template freemarkerTemplate = configuration.getTemplate("wordExport.ftl");
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
// 调用工具类的createDoc方法生成Word文档
file = createDoc(map,freemarkerTemplate,title,toDirFloder);
return file;
} private static File createDoc(Map<?, ?> dataMap, Template template,String filename,String toDirFloder) {
File f = new File(toDirFloder+"/"+filename+".doc");
Template t = template;
try {
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
t.process(dataMap, w);
w.close();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
return f;
} public String getImageBase(String src) {
if(src==null||src==""){
return "";
}
File file = new File(src);
if(!file.exists()) {
return "";
}
InputStream in = null;
byte[] data = null;
try {
in = new FileInputStream(file);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
try {
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
} }

导出压缩包工具类

Zipper.java

package testword;

import org.apache.commons.lang.StringUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert; import java.io.*;
import java.util.List; /**
* 用于制作zip压缩包
*/
public class Zipper {
private static final Logger log = LoggerFactory.getLogger(Zipper.class); /**
* 制作压缩包
*
*/
public static void zip(OutputStream out, List<FileEntry> fileEntrys,
String encoding) {
new Zipper(out, fileEntrys, encoding);
} /**
* 制作压缩包
*
*/
public static void zip(OutputStream out, List<FileEntry> fileEntrys) {
new Zipper(out, fileEntrys, null);
} /**
* 创建Zipper对象
*
* @param out
* 输出流
* @param filter
* 文件过滤,不过滤可以为null。
* @param srcFilename
* 源文件名。可以有多个源文件,如果源文件是目录,那么所有子目录都将被包含。
*/
protected Zipper(OutputStream out, List<FileEntry> fileEntrys,
String encoding) {
Assert.notEmpty(fileEntrys);
long begin = System.currentTimeMillis();
log.debug("开始制作压缩包");
try {
try {
zipOut = new ZipOutputStream(out);
if (!StringUtils.isBlank(encoding)) {
log.debug("using encoding: {}", encoding);
zipOut.setEncoding(encoding);
} else {
log.debug("using default encoding");
}
for (FileEntry fe : fileEntrys) {
zip(fe.getFile(), fe.getFilter(), fe.getZipEntry(), fe
.getPrefix());
}
} finally {
zipOut.close();
}
} catch (IOException e) {
throw new RuntimeException("制作压缩包时,出现IO异常!", e);
}
long end = System.currentTimeMillis();
log.info("制作压缩包成功。耗时:{}ms。", end - begin);
} /**
* 压缩文件
*
* @param srcFile
* 源文件
* @param pentry
* 父ZipEntry
* @throws IOException
*/
private void zip(File srcFile, FilenameFilter filter, ZipEntry pentry,
String prefix) throws IOException {
ZipEntry entry;
if (srcFile.isDirectory()) {
if (pentry == null) {
entry = new ZipEntry(srcFile.getName());
} else {
entry = new ZipEntry(pentry.getName() + "/" + srcFile.getName());
}
File[] files = srcFile.listFiles(filter);
for (File f : files) {
zip(f, filter, entry, prefix);
}
} else {
if (pentry == null) {
entry = new ZipEntry(prefix + srcFile.getName());
} else {
entry = new ZipEntry(pentry.getName() + "/" + prefix
+ srcFile.getName());
}
FileInputStream in;
try {
log.debug("读取文件:{}", srcFile.getAbsolutePath());
in = new FileInputStream(srcFile);
try {
zipOut.putNextEntry(entry);
int len;
while ((len = in.read(buf)) > 0) {
zipOut.write(buf, 0, len);
}
zipOut.closeEntry();
} finally {
in.close();
}
} catch (FileNotFoundException e) {
throw new RuntimeException("制作压缩包时,源文件不存在:"
+ srcFile.getAbsolutePath(), e);
}
}
} private byte[] buf = new byte[1024];
private ZipOutputStream zipOut; public static class FileEntry {
private FilenameFilter filter;
private String parent;
private File file;
private String prefix; public FileEntry(String parent, String prefix, File file,
FilenameFilter filter) {
this.parent = parent;
this.prefix = prefix;
this.file = file;
this.filter = filter;
} public FileEntry(String parent, File file) {
this.parent = parent;
this.file = file;
} public FileEntry(String parent, String prefix, File file) {
this(parent, prefix, file, null);
} public ZipEntry getZipEntry() {
if (StringUtils.isBlank(parent)) {
return null;
} else {
return new ZipEntry(parent);
}
} public FilenameFilter getFilter() {
return filter;
} public void setFilter(FilenameFilter filter) {
this.filter = filter;
} public String getParent() {
return parent;
} public void setParent(String parent) {
this.parent = parent;
} public File getFile() {
return file;
} public void setFile(File file) {
this.file = file;
} public String getPrefix() {
if (prefix == null) {
return "";
} else {
return prefix;
}
} public void setPrefix(String prefix) {
this.prefix = prefix;
}
}
}

使用控制器类

package testword;

import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; public class TestWord { @RequestMapping("/o_export")
public void export(HttpServletRequest request, HttpServletResponse response) {
WordUtils wordUtils = new WordUtils();
List<Zipper.FileEntry> flist = new ArrayList<Zipper.FileEntry>(); //这里要获取要导出的数据列表集合
List list = null;
//模板所在文件夹路径
String tplDir = null;
//模板word临时存储的位置
String toDirFloder=null

      //文件夹不存在,创建文件夹
      File dirFile=new File(toDirFloder);
      if (!dirFile.exists()){
        dirFile.mkdirs();
      }

        //要循环遍历的数据
for (Object e : list) {
//导出的word文件名称
String filename = null;
try {
File file = wordUtils.exportMillCertificateWord(request, response, enrollToMap(e, wordUtils), filename, tplDir, toDirFloder);
//这里表示压缩包下会有一个文件夹,名称是“学生信息表”,所有的word文件会放到这个文件夹底下
Zipper.FileEntry entry = new Zipper.FileEntry("学生信息表", file);
//把文件放到压缩包中
flist.add(entry);
} catch (IOException e1) {
e1.printStackTrace();
}
}
response.setContentType("application/x-download;charset=UTF-8");
try {
//这里的“学生信息表”是压缩包文件名
response.addHeader("Content-disposition", "filename=" + new String("学生信息表".getBytes("gb2312"), "iso8859-1") + ".zip");
Zipper.zip(response.getOutputStream(), flist, "GBK");

        //删除word临时保存的文件和文件夹
        File[] files=dirFile.listFiles();
        for (File f:files){
            f.delete();
        }
        dirFile.delete();

        } catch (IOException e) {
e.printStackTrace();
}
} public Map enrollToMap(Student s, WordUtils wordUtils) {
Map map = new HashMap(); //这里的name和sex为模板中占位符的名称 我模板中用的占位符是“${name}”,所以这里map集合的key是name
map.put("name", s.getName());
map.put("sex", s.getSex()); //获取图片URL地址后,调用方法生成BASE64格式
String photoBase64 = wordUtils.getImageBase("图片URL绝对地址");
map.put("photo", photoBase64);
return map;
}
}

JAVAWEB使用FreeMarker利用ftl把含有图片的word模板生成word文档,然后打包成压缩包进行下载的更多相关文章

  1. JAVA Freemarker + Word 模板 生成 Word 文档 (普通的变量替换,数据的循环,表格数据的循环,以及图片的东替换)

    1,最近有个需求,动态生成 Word 文当并供前端下载,网上找了一下,发现基本都是用 word 生成 xml 然后用模板替换变量的方式 1.1,这种方式虽然可行,但是生成的 xml 是在是太乱了,整理 ...

  2. springboot中使用freemarker生成word文档并打包成zip下载(简历)

    一.设计出的简历模板图以及给的简历小图标切图         二.按照简历模板图新建简历word文件 :${字段名},同时将图片插入到word中,并将建好的word文件另存为xml文件:    三.直 ...

  3. 关于根据模板生成pdf文档,差入图片和加密

    import com.alibaba.fastjson.JSONObject; import com.aliyun.oss.OSSClient; import com.itextpdf.text.pd ...

  4. 利用Java动态生成 PDF 文档

    利用Java动态生成 PDF 文档,则需要开源的API.首先我们先想象需求,在企业应用中,客户会提出一些复杂的需求,比如会针对具体的业务,构建比较典型的具备文档性质的内容,一般会导出PDF进行存档.那 ...

  5. 利用模板导出文件(二)之jacob利用word模板导出word文件(Java2word)

    https://blog.csdn.net/Fishroad/article/details/47951061?locationNum=2&fps=1 先下载jacob.jar包.解压后将ja ...

  6. 黄聪:利用OpenXml生成Word2007文档(转)

    原文:http://blog.csdn.net/francislaw/article/details/7568317 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 一Op ...

  7. 利用OpenXml生成Word2007文档

    一.OpenXml简介 利用C#生成Word文档并非一定要利用OpenXml技术,至少可以使用微软提供的Office相关组件来编程,不过对于Office2007(确切的说是Word.Excel和Pow ...

  8. JSP利用freemarker生成基于word模板的word文档

    利用freemarker生成基于word模板的word文档 freemarker简介 FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker与Web容器 ...

  9. qt 利用 HTML 生成PDF文档,不能显示jpg图片

    利用 QPrinter 和html 生成 pdf文档 其中用html语句有显示图片的语句 但只能显示png格式的图片,不能显示jpg格式图片. 经过排查:语法,文件路径等都正确,最终在stack ov ...

随机推荐

  1. Codeforces 193D - Two Segments(线段树)

    Codeforces 题目传送门 & 洛谷题目传送门 感觉这个 *2900 并不难啊,为什么我没想出来呢 awa 顺便膜拜 ycx 一眼秒掉此题 %%% 首先碰到这类题有两种思路,一是枚举两个 ...

  2. DTOJ 4030: 排列计数

    [题目描述] 求有多少个1到n的排列满足恰有$k$对在排列中相邻的数满足前小于后,答案对2012取模. [输入] 一行2个正整数$n,k$. [输出] 输出一个整数表示答案. [样例输入] 5  2 ...

  3. 睡眠或者重启windows,无法ssh连接或者pingVMware的虚机

    睡眠后无法直接ssh重连VMware主机问题 这个问题我在win8上出现过,win10看了下同事可以正常连,不知道其他有没有问题. 解决方法: 1.关闭vmnet8和vmnet0里面的 npcap 功 ...

  4. 简单mvc框架核心笔记

    简单mvc框架核心笔记 看了thinkphp5的源码,模仿写了一个简单的框架,有一些心得笔记,记录一下 1.目录结构 比较简单,没有tp那么复杂,只是把需要的核心类写了一些. 核心类库放在mykj里, ...

  5. oracle中char],varchar,varchar2

    VARCHAR.VARCHAR2.CHAR的区别 1.CHAR的长度是固定的,而VARCHAR2的长度是可以变化的, 比如,存储字符串"abc",对于CHAR (20),表示你存储 ...

  6. SpringBoot整合Shiro 三:整合Mybatis

    搭建环境见: SpringBoot整合Shiro 一:搭建环境 shiro配置类见: SpringBoot整合Shiro 二:Shiro配置类 整合Mybatis 添加Maven依赖 mysql.dr ...

  7. CAD简介

    Computer-aided design (CAD) is the use of computers (or workstations) to aid in the creation, modifi ...

  8. 轻松理解webpack热更新原理

    一.前言 - webpack热更新 Hot Module Replacement,简称HMR,无需完全刷新整个页面的同时,更新模块.HMR的好处,在日常开发工作中体会颇深:节省宝贵的开发时间.提升开发 ...

  9. 修改linux文件权限命令:chmod 转载至 Avril 的随笔

    Linux系统中的每个文件和目录都有访问许可权限,用它来确定谁可以通过何种方式对文件和目录进行访问和操作. 文件或目录的访问权限分为只读,只写和可执行三种.以文件为例,只读权限表示只允许读其内容,而禁 ...

  10. Android中的性能优化

    由于手机硬件的限制,内存和CPU都无法像pc一样具有超大的内存,Android手机上,过多的使用内存,会容易导致oom,过多的使用CPU资源,会导致手机卡顿,甚至导致anr.我主要是从一下几部分进行优 ...