Java 批量导出Word模板生成ZIP文件到浏览器默认下载位置

是不是你们要找的!是不是你们要找的!是不是你们要找的!

先看效果:

1.word模板格式

2.模板位置

3.需要的依赖

java 复制代码
        <!--POI-TL实现数据导出到word模板-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.0.M2</version>
        </dependency>
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.9.1</version>
        </dependency>
        <!--支持Zip-->
        <dependency>
            <groupId>net.lingala.zip4j</groupId>
            <artifactId>zip4j</artifactId>
            <version>2.11.5</version>
        </dependency>

4.直上代码

java 复制代码
    @Override
    public Result exportReportAAndF1List(HttpServletResponse response,List<Integer> ids) throws Exception {

        List<Map<String, Object>> arrayMap = new ArrayList<>();

        for(Integer sonId:ids) {
            //导出A 单个导出
            TestRecord testRecord = testRecordMapper.selectById(sonId);
            List<VehicleParts> vehiclePartsList = vehiclePartsMapper.selectList(new LambdaQueryWrapper<VehicleParts>().eq(VehicleParts::getModelId,
                    testRecord.getModelId()));
            Map<Integer, VehicleParts> vehiclePartsMap = vehiclePartsList.stream().collect(Collectors.toMap(VehicleParts::getId, vehicleParts -> vehicleParts));
            JSONObject vehicle = new JSONObject();
            Unit unit = null;
            if (StringUtils.isNotBlank(testRecord.getVehicleInfo())) {
                vehicle = JSONObject.parseObject(testRecord.getVehicleInfo());
                Integer unitId = vehicle.getInteger("unitId");
                if (unitId != null) {
                    unit = unitMapper.selectById(unitId);
                }
            }

            // 1 设置编码格式、文件名称
            response.setCharacterEncoding("utf-8");

            Map<String, Object> map = new HashMap<>();

            // 1.基本属性填充
            map.put("fName", "F" + testRecord.getModelId());
            map.put("fileName", Optional.ofNullable(testRecord.getFileName()).orElse("--"));
            map.put("modelName", Optional.ofNullable(testRecord.getModelName()).orElse("--")); //Optional.ofNullable().orElse("--")
            map.put("powerHours", (int) Math.floor(Optional.ofNullable(vehicle.getDouble("powerHours")).orElse(0.0)));
            map.put("plateNumber", Optional.ofNullable(vehicle.get("plateNumber")).orElse("--"));
            map.put("powerPackWorkingHours", (int) Math.floor(Optional.ofNullable(vehicle.getDouble("powerPackWorkingHours")).orElse(0.0)));
            if (!unit.getParent().equals(0)) {
                Unit unitFather = unitMapper.selectById(unit.getParent());
                map.put("unitName", Optional.ofNullable(unitFather.getUnitName() + "/" + unit.getUnitName()).orElse("--"));
            } else {
                map.put("unitName", Optional.ofNullable(unit.getUnitName()).orElse("--"));
            }
            map.put("powerPackYieldHours", (int) Math.floor(Optional.ofNullable(vehicle.getDouble("powerPackYieldHours")).orElse(0.0)));
            map.put("factoryDate", Optional.ofNullable(vehicle.get("factoryDate")).orElse("--"));
            map.put("taskPayloadWorkingHours", (int) Math.floor(Optional.ofNullable(vehicle.getDouble("taskPayloadWorkingHours")).orElse(0.0)));
            map.put("mileage", (int) Math.floor(Optional.ofNullable(testRecord.getMileage()).orElse(0.0)));
            map.put("createTime", Optional.ofNullable(testRecord.getCreateTime()).orElse("--"));
            map.put("remark", Optional.ofNullable(testRecord.getRemark()).orElse("--"));

            //list所属系统

            //拼接数据结构
            // 2.商品详情列表填充
            List<Map<String, Object>> goodsWordList = new ArrayList<>();

            //下面的行数
            List<FillData> data = data(testRecord.getDetail(), vehiclePartsMap);
            for (int i = 0; i < data.size(); i++) {
                Map<String, Object> goodsMap = new HashMap<>();
                goodsMap.put("id", i + 1);
                goodsMap.put("item", Optional.ofNullable(data.get(i).getItem()).orElse("--"));
                goodsMap.put("result", Optional.ofNullable(data.get(i).getResult()).orElse("--"));
                goodsMap.put("partsName", Optional.ofNullable(data.get(i).getPartsName()).orElse("--"));
                goodsMap.put("subsystemName", Optional.ofNullable(data.get(i).getSubsystemName()).orElse("--"));
                goodsMap.put("trueOrFalse", Optional.ofNullable(data.get(i).getTrueOrFalse()).orElse("--"));
                goodsWordList.add(goodsMap);
            }
            map.put("goods", goodsWordList);

            arrayMap.add(map);
        }

        // 设置响应的内容类型
        response.setContentType("application/zip");

        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");

        String zipName = URLEncoder.encode("F1检测信息报表.zip", "UTF-8").replaceAll("\\+", "%20");

        response.setHeader("Content-Disposition", "attachment;filename=" + zipName);

        try (ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream())){

            for (Map<String, Object> data : arrayMap){

                //使用 ByteArrayOutputStream 来创建内存中的 Word 文件
                ByteArrayOutputStream wordOut = new ByteArrayOutputStream();

                //数据写入模板
                XWPFDocument document = new MyXWPFDocument(Objects.requireNonNull(this.getClass().getResourceAsStream("/template/testAF1.docx")));
                // 读取模板
                WordExportUtil.exportWord07(document, data);

                document.write(wordOut);

                // 添加Word文件到Zip包中
                zipOutputStream.putNextEntry(new ZipEntry(data.get("fileName") + ".docx"));
                zipOutputStream.write(wordOut.toByteArray());
                zipOutputStream.closeEntry();
            }

            zipOutputStream.finish();

        }catch (IOException e){

            e.printStackTrace();
            throw new RuntimeException("Error creating ZIP file",e);

        }

        return Result.success();
    }
相关推荐
shepherd12624 分钟前
破局延时任务(上):为什么选择Spring Boot + DelayQueue来自研分布式延时队列组件?
java·spring boot·后端·1024程序员节
机灵猫25 分钟前
微服务中的服务熔断、降级与限流
java·数据库·微服务
雨夜之寂43 分钟前
第一章-第三节-Java开发环境配置
java·后端
郑清1 小时前
Spring AI Alibaba 10分钟快速入门
java·人工智能·后端·ai·1024程序员节·springaialibaba
zl9798991 小时前
SpringBoot-Web开发之数据响应
java·spring boot·后端
旷野说1 小时前
Spring Boot 1.x、2.x 3.x区别汇总
java·spring·tomcat·1024程序员节
没有bug.的程序员1 小时前
Spring Boot 起步:自动装配的魔法
java·开发语言·spring boot·后端·spring·1024程序员节
Hero | 柒1 小时前
设计模式之建造者模式
java·设计模式·1024程序员节
CodeLongBear1 小时前
帝可得智能售货机系统实战Day1:从环境搭建到区域管理功能落地 (1)
java·1024程序员节·ai + 若依框架
235162 小时前
【MySQL】慢查寻的发现和解决优化(思维导图版)
java·后端·sql·mysql·职场和发展·数据库开发·数据库架构