记一次使用poi-tl导出word,包含表格,表格里面图片
主要问题:导出的word里面包含大量图片,导出总是不显示里面的图片信息。
解决方案:最后选择把图片转为byte[],一个个放入PictureRenderData里面,下方附源码
需要导出的word如下图:
-
1.附 poi-tl官网(http://deepoove.com/poi-tl/#)
导入依赖可以查看官网,这里不在叙述。
本次导出word使用了里面的一个 LoopRowTableRenderPolicy(10.2 表格行循环的特定场景插件)。 -
2.导出模板
选用的是docx 需要注意的是,我把他放在了resource/wordTemplate/user.docx下面,这个地方导出的时候getResourceAsStream(“wordTemplate/user.docx”)。
模板如下:
-
3.实体类
@Data
@NoArgsConstructor
public class Grade {
private String title;
private String grade;
private String classes;
private String teacher;
private List<Student> studentList;
}
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class Student {
private String name;
private String gender;
private LocalDateTime time;
private PictureRenderData photo;
}
- 4业务代码
@ApiOperation(value = "导出word")
@PostMapping(value = "student/export/word")
public void exportStudent(HttpServletResponse response) throws IOException {
//存放要填充的数据
Grade grade = new Grade();
grade.setGrade("一年级");
grade.setClasses("一年级");
grade.setTeacher("老李");
grade.setTitle("一年级导出word");
List<Student> students=new ArrayList<>();
students.add(new Student().setName("老赵").setTime(LocalDateTime.now()).setGender("男"));
students.add(new Student().setName("老李").setTime(LocalDateTime.now()).setGender("男"));
students.add(new Student().setName("老胡").setTime(LocalDateTime.now()).setGender("男"));
students.add(new Student().setName("老张").setTime(LocalDateTime.now()).setGender("男"));
//自己的图片链接地址,根据自己业务需要,可能需要在下面students 里面一条一条拿
String url = "xxxx/xxxx/xxx.";
students.forEach(student -> {
// HttpDownloader hutool的转为字节
byte[] imageStream = HttpDownloader.downloadBytes(url);
Pictures.PictureBuilder pictureBuilder = Pictures.ofBytes(imageStream);
PictureRenderData pictureRenderData = pictureBuilder.size(100, 100).create();
student.setPhoto(pictureRenderData);
});
grade.setStudentList(students);
//以上自己业务代码 返回的实体类 放入render, XWPFTemplate.compile(in, config).render(grade)
//这是第一条说的表格行循环的插件,可以参考官网
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
Configure config = Configure.builder()
.bind("studentList", policy)
.bind("photo", new PictureRenderPolicy())
.build();
//getResourceAsStream 里面是自己的模板位置
InputStream in = this.getClass().getClassLoader().getResourceAsStream("wordTemplate/user.docx");
assert in != null;
XWPFTemplate template = XWPFTemplate.compile(in, config).render(grade);
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition", "attachment;filename=\"" + System.currentTimeMillis() + ".docx" + "\"");
OutputStream out = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(out);
template.write(bos);
bos.flush();
out.flush();
PoitlIOUtils.closeQuietlyMulti(template, bos, out);
}