最近项目需要,需要将文本信息下载为doc文件(带图片),小白通过在网上查找资料实现了这个功能
先引入freemarker的jar包
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.13</version>
</dependency>
制作模板文件:
新建一个word文件:
英文部分是后面需要替换的内容,插入图片,后面也需要替换
将文件另存为xml,编辑器打开xml文件,将上述英文部分用${....}替换,${....}中的内容是后台传递过来的值(你需要显示的内容),doc中的图片在xml中被解析成一长串的base64编码,需要用${image}代替base64编码。最后将xml文化后缀改为ftl,并将ftl文件放到你项目中
下面是后台代码:
建立工具类
package com.jhzj.common.utils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import com.jhzj.entity.bussiness.attendance.LeaveDto;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import sun.misc.BASE64Encoder;
public class WordUtil {
private Configuration configuration = null;
public WordUtil() {
configuration = new Configuration();
configuration.setDefaultEncoding("UTF-8");
}
/**
* 将文本信息转为word输出
* @param dto
* @throws Exception
*/
public File createDoc(LeaveDto dto) {
Map<String,Object> dataMap = new HashMap<>();
getData(dataMap,dto); //创建数据
configuration.setClassForTemplateLoading(this.getClass(), ""); //模板文件所在路径
Template t = null;
String fileName = dto.getUserName()+"-请假.doc";
File file = new File(fileName);
try {
t = configuration.getTemplate("leaveoff.ftl"); //获取模板文件
t.setEncoding("utf-8");
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName),"utf-8"));
t.process(dataMap, out); //将填充数据填入模板文件并输出到目标文件
out.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
return file;
}
/**
* 导出word 并提供下载
* @param response
*/
public void download(HttpServletResponse response,LeaveDto dto) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
File file = createDoc(dto);
String fileName = dto.getUserName()+"-请假.doc";
response.setContentType("application/msword;charset=utf-8");
response.addHeader("Content-Disposition", "attachment; filename=\""
+ new String(fileName.getBytes(),"iso-8859-1") + "\"");
bis = new BufferedInputStream(new FileInputStream(file));
bos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[10240];
int bytesRead;
while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
bis.close();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//获得数据
private void getData(Map<String,Object> dataMap, LeaveDto dto) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dataMap.put("userName", dto.getUserName());
dataMap.put("type", dto.getType());
dataMap.put("startTime", sdf.format(dto.getStartTime()));
dataMap.put("endTime", sdf.format(dto.getEndTime()));
dataMap.put("reason", dto.getReason());
System.out.println("=================="+dto.getPicture());
String base64 = getBase64(dto.getPicture());
dataMap.put("image", base64);
}
//获得图片的base64编码
private String getBase64(String imgUrl) {
ByteArrayOutputStream data = new ByteArrayOutputStream();
URL url = null;
InputStream in = null;
HttpURLConnection httpUrl = null;
byte[] by = new byte[1024];
try {
url = new URL(imgUrl);
httpUrl = (HttpURLConnection)url.openConnection();
httpUrl.connect();
in = httpUrl.getInputStream();
int len = -1;
while((len = in.read(by)) != -1) {
data.write(by, 0, len);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data.toByteArray());
}
}
Controller代码:
/**
* 下载信息
* @param id 请假id
* @return
*/
@RequestMapping(value = "/download")
@ResponseBody
public void downloadInfo(HttpServletResponse response,Integer id) {
//if (doSecurityIntercept(Const.RESOURCES_TYPE_BUTTON){
try {
WordUtil wd = new WordUtil();
LeaveDto dto = service.checkInfo(id);
wd.download(response, dto);
} catch (BussinessException e) {
e.printStackTrace();
}catch (Exception e) {
logger.error(e.toString(), e);
e.printStackTrace();
}
//}
}
备注:如果模板是表格的话,表头的第一行需要保留。
在列表前加入<#list list as l>(在它的头上加一个<#list 你的集合名称 as xxxx>),并在结尾加上</#list>,修改list内容,在要输出的名字前面加上l.。如xuehao,修改为l.xuehao。这样有点像EL表达式的使用。
表格循环:
private void getData(Map<String, Object> dataMap) {
dataMap.put("title", "标题");
dataMap.put("nian", "2016");
dataMap.put("yue", "3");
dataMap.put("ri", "6");
dataMap.put("shenheren", "lc");
List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
for (int i = 0; i < 10; i++) {
Map<String,Object> map = new HashMap<String,Object>();
map.put("xuehao", i);
map.put("neirong", "内容"+i);
list.add(map);
}
dataMap.put("list", list);
}
以上代码都是本人亲测可用!