使用了freemarker模板填充占位符的方式来生成word文档,支持跨平台。
制作Word模板
将制作好的Word模板.docx
另存为.xml
格式,修改xml文件的内容符合freemarker解析规范;并将xml文件的后缀名改为.ftl
就行了。
创建Word模板具体过程可参考:使用FreeMarker自动生成Word文档
环境
Java 8
SpringBoot 2.3.10
<!-- freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
Word操作工具类
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
/**
* @description: word工具类
*/
@Component
public class DocUtil {
private Configuration configuration = null;
public DocUtil() {
// 设置版本号
configuration = new Configuration(Configuration.VERSION_2_3_0);
configuration.setDefaultEncoding("UTF-8");
}
/**
* 生成插入数据后的Word文件
*
* @param filename:目标文件名(要带上后缀名)
* @param reportTemplate 模板名称
* @param response:
* @param data:要写入的数据
*/
public void exportReport(String filename, String reportTemplate, HttpServletResponse response, Map<String, Object> data) {
BufferedInputStream inputStream = null;
BufferedOutputStream outputStream = null;
try {
// 获取写入数据后的文件
File outFile = writeReport(reportTemplate, filename, data);
response.reset();
response.setCharacterEncoding("UTF-8");
// 设置内容类型为Word格式
response.setContentType("application/msword");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
response.setContentType("application/octet-stream");
inputStream = new BufferedInputStream(new FileInputStream(outFile));
outputStream = new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[inputStream.available() + 1024];
int num = 0;
while ((num = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, num);
}
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null)
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (outputStream != null)
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* @param templateName:模板文件名
* @param filename:目标文件名
* @param data:要写入模板文件的数据
*/
public File writeReport(String templateName, String filename, Map<String, Object> data) {
// 设置模板加载路径
configuration.setClassForTemplateLoading(this.getClass(), "/template");
// 允许为 null
configuration.setClassicCompatible(true);
File outFile = new File(filename);
try {
Template template = configuration.getTemplate(templateName);
Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8));
// 将数据填充到模板并写入目标文件
template.process(data, writer);
writer.close();
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
return outFile;
}
}
接下来的操作就是查询数据并处理,然后调用工具类的方法就行了。
注意:
-
Map中的Key必须和模板中的对应,否则会报错。
-
Word试卷的题目、选项是用表格(表格的边框设置不可见)模板的。
Word试卷模板设置可参考:Java用freemarker导出word