Java查询多条数据放入word模板 多个word文件处理成zip压缩包并在前端下载.zip文件

需求: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);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

最后前端处理进行下载即可。

相关推荐
曹牧1 小时前
C#:空合并运算符
java·前端·数据库
布吉岛的石头2 小时前
Java 程序员第 50 阶段2:预训练的目标函数:自回归语言建模本质
java·开发语言·人工智能·深度学习·回归·transformer
golang学习记2 小时前
IDEA 2026年的玩法已经完全不同
java·ide·intellij-idea
小羊没烦恼!2 小时前
铁道部新客票系统设计(二)
开发语言·前端·数据库·python·oracle·c#·php
紧跟先前的步伐2 小时前
Go AI Agent 实战 05|Temperature 与生成参数:让模型输出可控
java·人工智能·golang
金銀銅鐵2 小时前
[Java] 展示添加元素时 ArrayList 的内部变化
java·后端·ai编程
斌糖雪梨3 小时前
spring auth 核心流程详解
java·后端·spring
文丑颜不良啊4 小时前
LeetCode201~225题目解析
java·leetcode
智能直播5 小时前
RK3518:1.5G 内存 + 8G 存储,如何跑起硬件编解码、Web、AI 识别、绿幕特效
前端·人工智能·5g
掘金酱6 小时前
【10.24 特别活动】AI 时代,程序员的新饭碗在哪里?
前端·人工智能·后端