在工作中又遇到要导出word,根据模板导出,里面有一部分内容数据事动态的,需要循环根据数据导出。
一、首先准备word模板
1、在word里面讲格式调整好,在需要导出图片的地方填充图片。
需要填充数据的地方用字段名代替。以便于修改为el表达式,也可以直接在模板里面直接用EL表达式,定义好,比如这样:
2、另存为 类型为 word 2003 xml
3、将xml文件打开,可以看到已经是xml格式了。可以将内容全部复制到xml格式化网站,进行格式化之后,这样就好看多了嘛
4、然后将文件复制到你项目,改文件后缀为ftl
二、准备导出数据
1、首先在项目里面引入freemaker依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
<version>2.6.1</version>
</dependency>
2、准备要导出的数据结构,这里只展示几个字段
@Data
public class RecordExportTO implements Serializable { private String title; private String feedbackName; private String feedbackPhone; private String diagnosisNo; private List<StTemplateQuestion> questionsList;//动态数据内容 private String faultImg; private List<ExportWordImgVo> faultImgList;//图片集合 }
3、修改模板,根据数据结构字段,将需要填充数据的地方,修改为EL表达式。${()!} 加括号!号表示可以为null
动态数据内容部分,根据你需要动态输出的,部分进行循环,我这里是表格一行循环。
在循环里面,根据自己的业务处理
图片处理:
注意!!!
图片base64编码内容,两个>${img.content}< 中间不能有空格!
三、导出
我是接口http导出
@Autowired
private Configuration configuration; //freemarker.template.Configuration;
@GetMapping("/export/{id}")
public void exportById(@PathVariable Integer id,HttpServletResponse response) {
RecordExportTO data =new RecordExportTO();
//准备数据部分,省略--
//图片 List<ExportWordImgVo> faultImgList = findXls(record.getFaultImg(),xls);//这里这个函数是我得业务逻辑处理,返回的是多张图片的base64编码 data.setFaultImgList(faultImgList);
//导出 configuration.setDefaultEncoding("utf-8");
try { response.setContentType("application/msword");
response.setHeader("Content-Disposition", "attachment;filename=\"" + new String(record.getDiagnosisNo().getBytes("utf-8"), "iso8859-1") + ".doc\"");//导出word文件名
response.setCharacterEncoding("utf-8"); final Template template = configuration.getTemplate("word/record.ftl", "utf-8");//模板位置
template.process(data, new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), "utf-8")));
} catch (Exception e) {
log.error("导出失败", e);
}finally {
try {
response.getOutputStream().close();
} catch (IOException e) { e.printStackTrace(); }
}
}
//根据url返回图片的base64编码 导出的word里面需要base64格式的 private String getImgBase64(String url){ HttpClient client = HttpClients.custom().build(); HttpGet get = new HttpGet(url); HttpResponse response; try { response = client.execute(get); if (response.getStatusLine().getStatusCode() == 200) { // 得到实体 HttpEntity entity = response.getEntity(); byte[] data = EntityUtils.toByteArray(entity); return new String(Base64.encodeBase64(data)); } else { logger.error("下载文件url 错误返回:{}",response); return null; } } catch (IOException e) { e.printStackTrace(); logger.error("下载文件url 错误:",e); } return null; }
//图片class
public class ExportWordImgVo implements Serializable {
private String id;//自定义id
private String name;//图片名
private String content;//图片base64码
}
访问这个接口,就可以导出啦