这一篇和上一篇word模板下载到本地有一些区别,这里是下载到用户端的浏览器,其实是返回二进制给浏览器
如果你想看word怎么转成ftl模板的请看springboot使用freemarker模板生成word文档
这篇博客参考的ssm实现文件下载
一、工具类WordUntil
import com.alibaba.fastjson.JSON;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Map;
/**
* @author lenovo
*/
@Slf4j
public class WordUtil {
/**
* 生成word文件并返回二进制
*
* @param dataMap word中需要展示的动态数据,用map集合来保存
* @param templateName word模板名称,例如:model.ftl
* @param fileName 生成的文件名称,例如:Test.doc
*/
public static byte[] createWordByte(Map<String, Object> dataMap, String templateName, String fileName) throws IOException {
File outFile = null;
Writer out = null;
try {
//创建配置实例
Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
//设置编码
configuration.setDefaultEncoding("utf-8");
//ftl模板文件
configuration.setClassForTemplateLoading(WordUtil.class, "/templates/down");
//获取模板
Template template = configuration.getTemplate(templateName);
//输出文件
outFile = new File(File.separator + fileName);
//将模板和数据模型合并生成文件
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8));
//生成文件
template.process(dataMap, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
assert out != null;
out.flush();
out.close();
}
return getWordByte(outFile);
}
/**
* 根据文件生成二进制数组
*
* @param outFile
* @return
*/
private static byte[] getWordByte(File outFile) {
byte[] wordByte = null;
try {
FileInputStream fis = new FileInputStream(outFile);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
fis.close();
bos.close();
wordByte = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return wordByte;
}
/**
* 生成word文件到本地
*
* @param dataMap word中需要展示的动态数据,用map集合来保存
* @param templatePath word模板的路径
* @param templateName word模板名称,例如:model.ftl
* @param filePath 文件生成的目标路径,例如:D:\\freemarker
* @param fileName 生成的文件名称,例如:Test.doc
*/
public static void createWordToLocal(Map<String, Object> dataMap, String templatePath, String templateName, String filePath, String fileName) throws IOException {
File outFile = null;
Writer out = null;
try {
//创建配置实例
Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
//设置编码
configuration.setDefaultEncoding("utf-8");
//ftl模板文件
configuration.setClassForTemplateLoading(WordUtil.class, templatePath);
//获取模板
Template template = configuration.getTemplate(templateName);
//输出文件
outFile = new File(filePath + File.separator + fileName);
//如果输出目标文件夹不存在,则创建
if (!outFile.getParentFile().exists()) {
if (!outFile.getParentFile().mkdirs()) {
log.error("创建文件到本地失败 dataMap:{}", JSON.toJSONString(dataMap));
}
}
//将模板和数据模型合并生成文件
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8));
//生成文件
template.process(dataMap, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
assert out != null;
out.flush();
out.close();
}
}
}
这里有两个静态方法入口
- 一个是返回word模板的二进制数组,由controller层返回这个二进制,
- 一个是保存word模板到本地,
这里主要是看看返回二进制数组的,
保存本地的请往SpringBoot以freemarker为word的模板下载文件到本地(1)
二、Controller层的写法
@RequestMapping(value = "/downPurchaseOrder.do")
@ResponseBody
public ResponseEntity<byte[]> downPurchaseOrder(Long id) {
Map<String, Object> dataMap = new HashMap<String, Object>(2);
byte[] fileByte = null;
try {
//可以认为dataMap和model扮演的角色一样
dataMap.put("num", 1);
fileByte = WordUtil.createWordByte(dataMap, "model.ftl", "测试单.doc");
HttpHeaders headers = new HttpHeaders();
headers.setContentDispositionFormData("attachment", URLEncoder.encode("测试.doc", "utf-8"));
return new ResponseEntity<byte[]>(fileByte, headers, HttpStatus.CREATED);
} catch (Exception e) {
log.error("导出测试单失败 id:{}", id, e);
}
return null;
}
三、前端的写法
<a href="/down.do?id=1" title="导出">下载word</a>
这样就完成了下载到用户端的操作
四、下载的文件的起名
如果你想让下载的文件的名称是后端定的,你就可以按上面的来
如果你想让下载的文件的名称是前端定的,你就可以按下面的来
HttpHeaders headers = new HttpHeaders();
headers.setContentDispositionFormData("attachment", URLEncoder.encode("测试单.doc", "utf-8"));
return new ResponseEntity<byte[]>(fileByte, headers, HttpStatus.CREATED);
换成
return new ResponseEntity<byte[]>(fileByte, HttpStatus.CREATED);
前端换成这样
<a href="/down.do?id=1" title="导出" download="测试单.doc">下载word</a>