一:进行模板创建
我们要进行模板导出的话 需要首先将前台的数据传到后台再解析成流文件存储到相应位置,但是要将word以模板格式进行导出的话,我借助了freemark模板殷勤来进行实现,
我们需要在项目开始前,导入maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
然后找出我们需要的模板
首先需要一份想要导出的模板,通过office软件转换成xml格式 (一定要根据office 不是wps toon过“另存为”的方式转换格式不能手动更改拓展名来进行格式转换;
之后将xml文件放入到项目里面,我放到了 word导出对应的包下,并将其扩展名改为.ftl,使得该模板文件可以被模板殷勤识别并应用。
jpg是模板导出需要用到的图片,只有红色箭头标注的是本项目必须的文件 其余几个可以忽略,当然图片和导出样例.ftl 可以自己放到别的 写对他们的路径就可以(我放在了别处这只是演示)。
二:进行文件导出的工具类的创建
工具类的作用包含 编码文件名、获取下载/导出路径、进行模板导出的处理
编码文件名:
UUID.randomUUID 这个方法是给文件加上一个唯一字符串 防止文件名称重复 导致的比如数据覆盖等错误。 filename是自定义的文件名称
/**
* 编码文件名
*/
public static String encodingFilename(String filename) {
filename = UUID.randomUUID().toString() + "_" + filename + ".doc";
return filename;
}
获取下载路径 定义好要将该文档导出到哪一个文件里面 设置文件导出路径
代码解释:
NiuaConfig。getDownloadPath()是我采用的框架的自定义方法不通用,作用是获取到导出文件存储的根路径:“D://code/download//” 这都是可以自己定义的甚至不用方法直接写上去也可以。
if判断是根据我的方法来的 防止服务器没有该文件夹 进行自动创建。
/**
* 获取下载路径
*
* @param filename 文件名称
*/
public static String getAbsoluteFile(String filename) {
String downloadPath = NiuaConfig.getDownloadPath() + filename;
File desc = new File(downloadPath);
if (!desc.getParentFile().exists()) {
desc.getParentFile().mkdirs();
}
return downloadPath;
}
模板导出核心方法:
代码解释
在准备数据这一块 采用的是map 根据freemark里面加了$符号的变量进行的赋值
采用map的赋值格式:
前面的是实体类的字段名,后面是想要对其进行的赋值。
dataMap.put("classPath", "com.freemark.hello");
dataMap.put("className", "AutoCodeDemo");
如:ftl里面${topScore.goodScoreMin} 在map里面为其赋值 就会在相应的模板里面进行显示
核心类代码:
public static ResultJson exportWordDoc(Map<String, Object> data, String wordName) throws IOException, TemplateException {
/** 初始化配置文件 **/
Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
/** 设置编码 **/
configuration.setDefaultEncoding("utf-8");
/** 我的ftl文件是放在D盘的**/
String fileDirectory = NiuaConfig.getFtlPath();
//String fileDirectory = "D:\\niua-dev\\niua-admin\\src\\main\\resources\\word";
/** 加载文件 **/
configuration.setDirectoryForTemplateLoading(new File(fileDirectory));
/** 加载模板 **/
Template template = configuration.getTemplate("导出样例.ftl");
/** 准备数据 **/
Map<String, Object> dataMap;
dataMap = data;
String fileName = encodingFilename(wordName);
/** 指定输出word文件的路径 **/
String outFilePath = getAbsoluteFile(fileName);
File docFile = new File(outFilePath);
FileOutputStream fos = new FileOutputStream(docFile);
Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
template.process(dataMap, out);
if (out != null) {
out.close();
}
return ResultJson.ok(fileName);
}
对于word模板中图片处理 在对mapdata进行赋值的时候 根据图片的url将其转换为输入流数据,放入mapdata中
public static String getImageStr(String imgUrl) {
imgUrl = NiuaConfig.getProfile() + "\\" + "upload" + "\\" +imgUrl;
InputStream in = null;
byte[] data = null;
try {
in = new FileInputStream(imgUrl);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
}
三:对于 datamap中的数据 、导出word中的数据 、以及导出样例ftl 相互对应关系
datamap:
这里的data采用了map存储,
data:
data.put("number", number);
key value格式我就不介绍了 记住这个number 再ftl文件里面通过${number} 来对其进行值的读取,保存在word文件上
ftl:
word:
对应的考生编号就会根据number进行显示出来。
如果对应的表格需要用到多行一样的格式,这时候需要采用 freemark的遍历list方法。
eg: