需求:Java查询多条数据放入word模板 多个word文件处理成zip压缩包并在前端下载.zip文件
解决方法:在模板的位置定义参数如 {{name}} {{age}}等等,使用 poi 处理
伪代码:
- @PostMapping("/exportPracticeAppr")
- public String exportPracticeAppr(HttpServletResponse response, @RequestBody ExportToExcelParamDto paramDto) throws IOException {
- //查询数据 ExportToWordByPracticeApprDto为模板中的参数
- List
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
replaceMap = BeanUtil.beanToMap(apprDto); - Map
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
placeholders) throws IOException, InvalidFormatException { - //处理普通word文字 不包含表格
- for (XWPFParagraph paragraph : document.getParagraphs()) {
- List
runs = paragraph.getRuns(); - for (XWPFRun run : runs) {
- String text = run.getText(0);
- if (text != null) {
- for (Map.Entry
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
runs = paragraph.getRuns(); - for (XWPFRun run : runs) {
- String text = run.getText(0);
- if (text != null) {
- for (Map.Entry
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);
- }
- }
- }
- }
- }
- }
- }
- }
- }
最后前端处理进行下载即可。