1.创建Freemarker模板文件
1.1 新建word文档,输入模板数据;
1.2 将word文档另存为xml文件(必须是另存为,不是直接修改后缀名);
1.3 打开xml文件,将需要从数据库或动态获取的数据,使用${xx}符号替换,如:word文档上有“姓名:张三”,具体姓名需要从数据库动态获取,则将“张三”替换为“${name}”,name需要和Java代码中Map的key值保持一致;
1.4 将xml文件的后缀名修改为“ftl”(根据实际测试,直接使用1.3步的xml文件作为模板文件,也可以);
2.引入jar包
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
3.工具类
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import java.io.*;
import java.util.Map;
public class WordUtil {
//配置信息
private static Configuration configuration = null;
//模板文件的位置
private static String tempPath;
public WordUtil() {
if(configuration == null){
configuration = new Configuration(Configuration.VERSION_2_3_23);
configuration.setDefaultEncoding("UTF-8");
}
if(tempPath == null ||tempPath.length()==0){
//装载模板文件目录
String filePath = this.getClass().getClassLoader().getResource("/").getPath();
int end = filePath.lastIndexOf("WEB-INF/");
String basePath = filePath.substring(0,end);
tempPath = basePath + "WEB-INF/page/temp/";
}
}
public byte[] getByteWord(Map dataMap, String tempName) throws IOException {
byte[] content = null;
File file = null;
InputStream in = null;
try {
//模板文件路径
File readFile = new File(tempPath);
configuration.setDirectoryForTemplateLoading(readFile);
//加载模板文件
Template template = configuration.getTemplate(tempName);
//创建临时文件,用于保存要导出的数据
file = new File("report.doc");
//这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
Writer w = new OutputStreamWriter(new FileOutputStream(file), "utf-8");
//填充数据
template.process(dataMap, w);
//将临时文件数据读入文件流
in = new FileInputStream(file);
content=new byte[(int)file.length()];
in.read(content);
} catch (TemplateException e) {
e.printStackTrace();
} finally {
if(in != null) in.close();
//删除临时文件
if(file != null) file.delete();
}
return content;
}
public static HttpHeaders setResponseHeaderWord(String fileName){
HttpHeaders headers = new HttpHeaders();
try {
headers.add("Content-Disposition", "attachment;filename="+new String(fileName.getBytes("gbk"), "iso8859-1")+".doc");
headers.setContentType(MediaType.valueOf("application/msword"));
}catch (Exception e){
e.printStackTrace();
}
return headers;
}
}
4.接口类
@Override
public byte[] exportReportInfo(Integer id) {
byte[] bytes = null;
try {
//从数据库获取数据,Map中key需要和模板文件中${}中的值保持一致
Map map = this.exportMapper.selectReportExport(id);
//"<w:p></w:p>"为word文档支持的换行符号,将需要换行的地方进行替换
map.put("plan",map.get("plan").toString().replace("\n","<w:p></w:p>"));
//创建对象,初始化参数
WordUtil wordUtil = new WordUtil();
//获取需要导出的字节数组
bytes = wordUtil.getByteWord(map,"report.xml");
} catch (IOException e) {
e.printStackTrace();
}
return bytes;
}
4.执行导出操作
/*导出word*/
@RequestMapping("/exportReport")
public ResponseEntity<byte[]> exportReport(Integer id){
//设置word文件名
String fileName = "员工信息";
byte[] value = null;
try {
//获取要导出的数据
value = this.dataService.exportReportInfo(id);
}catch (Exception e){
e.printStackTrace();
}
//设置HttpHeaders,设置fileName编码,排除导出文档名称乱码问题
HttpHeaders headers = WordUtil.setResponseHeaderWord(fileName);
return new ResponseEntity(value,headers, HttpStatus.OK);
}
5.注意事项
5.1导出的word文档名称,需要使用.doc后缀,测试时使用.docx后缀,导出的文件出现异常;