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);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

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

相关推荐
MacroZheng2 分钟前
横空出世!MyBatis-Plus 同款 ES ORM 框架,用起来够优雅!
java·后端·elasticsearch
Asort15 分钟前
JavaScript 从零开始(六):控制流语句详解——让代码拥有决策与重复能力
前端·javascript
无双_Joney33 分钟前
[更新迭代 - 1] Nestjs 在24年底更新了啥?(功能篇)
前端·后端·nestjs
在云端易逍遥35 分钟前
前端必学的 CSS Grid 布局体系
前端·css
ccnocare36 分钟前
选择文件夹路径
前端
艾小码37 分钟前
还在被超长列表卡到崩溃?3招搞定虚拟滚动,性能直接起飞!
前端·javascript·react.js
闰五月38 分钟前
JavaScript作用域与作用域链详解
前端·面试
泉城老铁41 分钟前
idea 优化卡顿
前端·后端·敏捷开发
前端康师傅41 分钟前
JavaScript 作用域常见问题及解决方案
前端·javascript