需求:Java查询多条数据放入word模板 多个word文件处理成zip压缩包并在前端下载.zip文件
解决方法:在模板的位置定义参数如 {{name}} {{age}}等等,使用 poi 处理
伪代码:
java
@PostMapping("/exportPracticeAppr")
public String exportPracticeAppr(HttpServletResponse response, @RequestBody ExportToExcelParamDto paramDto) throws IOException {
//查询数据 ExportToWordByPracticeApprDto为模板中的参数
List<ExportToWordByPracticeApprDto> practiceApprExport = baseService.practiceApprExport(paramDto);
if (practiceApprExport != null && !practiceApprExport.isEmpty()) {
// 创建一个zip文件,并打开一个ZipOutputStream来写入文件
FileOutputStream fos = new FileOutputStream(paramDto.getActivityName() + "demo.zip");
ZipOutputStream zos = new ZipOutputStream(fos);
try {
//获取word模板文件
InputStream resourceAsStream = TrActivityGroupServiceImpl.class.getClassLoader().getResourceAsStream("word/导出模板.docx");
XWPFDocument doc = new XWPFDocument(Objects.requireNonNull(resourceAsStream));
//循环处理文件
for (ExportToWordByPracticeApprDto apprDto : practiceApprExport) {
Map<String, Object> replaceMap = BeanUtil.beanToMap(apprDto);
Map<String, Object> resultMap = new HashMap<>();
replaceMap.forEach((placeholder, replacement) -> resultMap.put("{{" + placeholder + "}}", replacement));
replacePlaceholders(doc, resultMap);
// 将Word文档保存为临时文件
File tempFile = File.createTempFile("demo", DOCX);
FileOutputStream tempOut = new FileOutputStream(tempFile);
doc.write(tempOut);
tempOut.close();
// 将临时文件添加到zip文件中 表示压缩包中的文件名称 aa.docx
ZipEntry zipEntry = new ZipEntry("aa.docx");
zos.putNextEntry(zipEntry);
FileInputStream fis = new FileInputStream(tempFile);
IOUtils.copy(fis, zos);
fis.close();
zos.closeEntry();
tempFile.delete();
}
// 关闭zip文件输出流
zos.close();
doc.close();
} catch (Exception e) {
logger.error("文件导出错误{}", e.getMessage());
}
}
// 返回zip文件内容
byte[] zipBytes = IOUtils.toByteArray(Files.newInputStream(Paths.get("demo.zip")));
response.reset();
response.setContentType("application/zip");
response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode("demo.zip", "UTF-8"));
response.setContentLength(zipBytes.length);
OutputStream out = response.getOutputStream();
out.write(zipBytes);
out.flush();
out.close();
return "redirect:/";
}
private void replacePlaceholders(XWPFDocument document, Map<String, Object> placeholders) throws IOException, InvalidFormatException {
//处理普通word文字 不包含表格
for (XWPFParagraph paragraph : document.getParagraphs()) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
String text = run.getText(0);
if (text != null) {
for (Map.Entry<String, Object> entry : placeholders.entrySet()) {
if (text.contains(entry.getKey())) {
text = text.replace(entry.getKey(), entry.getValue() != null ? (String) entry.getValue() : "");
run.setText(text, 0);
}
}
}
}
}
// 处理替换表格中的占位符
for (XWPFTable table : document.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
String text = run.getText(0);
if (text != null) {
for (Map.Entry<String, Object> entry : placeholders.entrySet()) {
if (text.contains(entry.getKey())) {
//获取、处理图片略
...
...
int format = XWPFDocument.PICTURE_TYPE_PNG;
//图片地址
BufferedImage image = ImageIO.read(new URL(value));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//suffix为图片的后缀 .png
ImageIO.write(image, suffix, outputStream);
byte[] imageBytes = outputStream.toByteArray();
//后两个参数是宽高
run.addPicture(new ByteArrayInputStream(imageBytes), format, fileName, Units.toEMU(80), Units.toEMU(40));
//替换文字 图片和文字如果都展示
text = text.replace(entry.getKey(), entry.getValue() != null ? (String) entry.getValue() : "");
run.setText(text, 0);
}
}
}
}
}
}
}
}
}
最后前端处理进行下载即可。