记录一次使用poi-tl将数据填充到docx中并下载(单独下载docx,批量下载zip)

话不多说,直接上代码:

  • 相关代码

配置文件application.yml中关于路径的配置

public void exportExperimentalData(ExportExperimentalDataReqVo reqVo, Long userId, HttpServletResponse response, HttpServletRequest request) {
    List<String> experimentalIds = reqVo.getExperimentalIds();
    List<ExperimentalDataIndex> list = new ArrayList<>();
    for (String experimentalId : experimentalIds) {
        ExperimentalDataIndex experimentalDataIndex = searchService.searchExperimentalById(experimentalId, EsIndexEnum.EXPERIMENTAL_DATA_INDEX.getIndexName());
        list.add(experimentalDataIndex);

        // 新增用户下载记录
        UserDownloadRecord downloadRecord = new UserDownloadRecord();
        downloadRecord.setUserId(userId);
        downloadRecord.setLiteratureId(experimentalId);
        downloadRecord.setTitle(experimentalDataIndex.getExperimentalTopic());
        downloadRecord.setSummary(experimentalDataIndex.getExperimentalConclusion());
        downloadRecord.setAuthor(experimentalDataIndex.getRecorder());
        downloadRecord.setDataType(2);//实验数据
        downloadRecord.setFinishTime(experimentalDataIndex.getFinishTime());
        downloadRecord.setCreateId(userId);
        downloadRecord.setCreateTime(new Date());
        userDownloadRecordMapper.insert(downloadRecord);
    }

    // 如果是单条下载 则下载为word  批量下载是zip格式
    if (list.size() == 1) {
        ExperimentalDataIndex experimentalDataIndex = list.get(0);
        String filePath = fileRoot;
        this.downloadExperimentalSingle(experimentalDataIndex, filePath, response, request);
    } else {
        String filePath = fileRoot + File.separator + "zip_path" + System.currentTimeMillis() + File.separator;
        this.downloadExperimentalBatch(list, filePath, response, request);
    }
}

/**
 * 批量下载
 *
 * @Param  list   
 * @Param  filePath   
 * @Param  response   
 * @Param  request     
 * @Return void
 **/
private void downloadExperimentalBatch(List<ExperimentalDataIndex> list, String filePath, HttpServletResponse response, HttpServletRequest request) {

    try {
        for (ExperimentalDataIndex experimentalDataIndex : list) {
            Map<String, Object> wordDataMap = new HashMap<>(32);
            wordDataMap.put("experimentalTopic", experimentalDataIndex.getExperimentalTopic());
            wordDataMap.put("recorder", userMapper.selectById(Long.parseLong(experimentalDataIndex.getRecorder())).getNickName());
            wordDataMap.put("major", experimentalDataIndex.getMajor());
            wordDataMap.put("classes", experimentalDataIndex.getClasses());
            wordDataMap.put("analyticalMethods", experimentalDataIndex.getAnalyticalMethods());
            wordDataMap.put("finishTime", experimentalDataIndex.getFinishTime());
            wordDataMap.put("experimentalIndicators", experimentalDataIndex.getExperimentalIndicators());
            wordDataMap.put("testConditions", experimentalDataIndex.getTestConditions());
            wordDataMap.put("experimentalScheme", experimentalDataIndex.getExperimentalScheme());
            // 实验附图
            List<ExperimentalDataImg> experimentalDataImgList = experimentalDataImgMapper.selectList(new
                    LambdaQueryWrapper<ExperimentalDataImg>().eq(ExperimentalDataImg::getExperimentalId,
                    experimentalDataIndex.getId()));

            // 附图导出封装类
            List<ExperimentalDataImgExportVo> imgExportVos = new ArrayList<>();

            int code = 1;
            for (ExperimentalDataImg experimentalDataImg : experimentalDataImgList) {
                ExperimentalDataImgExportVo experimentalDataImgExportVo = BaseDtoConvert.tToV(experimentalDataImg, ExperimentalDataImgExportVo.class);
                experimentalDataImgExportVo.setCode(code);
                if (StringUtils.isEmpty(experimentalDataImgExportVo.getRemarks())) {
                    experimentalDataImgExportVo.setRemarks("无");
                }
                imgExportVos.add(experimentalDataImgExportVo);
                code++;
            }
            wordDataMap.put("experimentalImg", imgExportVos);
            wordDataMap.put("experimentalConclusion", experimentalDataIndex.getExperimentalConclusion());

            String downloadFileName =
                    experimentalDataIndex.getExperimentalTopic() + System.currentTimeMillis() + ".docx";
            String savePath = filePath + downloadFileName;
            if (!FileUtil.exist(filePath)) {
                FileUtil.mkdir(filePath);
            }
            // 添加配置 循环表格行(实验附图)
            LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
            Configure config = Configure.builder()
                    .bind("experimentalImg", policy).build();
            //渲染文件
            XWPFTemplate compile = XWPFTemplate.compile("./template/实验数据导出模板_template.docx", config);
            compile.render(wordDataMap);
            compile.writeToFile(savePath);
        }

        // 设置压缩后的文件名
        String zipFileName = "实验数据.zip";
        // 压缩文件保存的路径
        String toPath = fileRoot + zipFileName;
        // 要压缩的文件目录
        String zipPath = filePath;
        ZipUtil.zip(zipPath, toPath);
        // 压缩完之后删除原文件
        FileUtils.deleteDirectory(new File(zipPath));

        try {
            File file = new File(toPath);
            String fileName = URLEncoder.encode(file.getName(), "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType("application/zip");
            response.setContentLength((int) file.length());

            try (InputStream inputStream = new FileInputStream(file);
                 OutputStream outputStream = response.getOutputStream()) {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    } catch (Exception e) {
        throw new ServiceException("下载实验数据失败!!" + e.getMessage());
    }
}

/**
 * 单独下载
 *
 * @Param  experimentalDataIndex  
 * @Param  filePath   
 * @Param  response   
 * @Param  request     
 * @Return void
 **/
private void downloadExperimentalSingle(ExperimentalDataIndex experimentalDataIndex, String filePath, HttpServletResponse response, HttpServletRequest request) {
    Map<String, Object> wordDataMap = new HashMap<>(32);
    wordDataMap.put("experimentalTopic", experimentalDataIndex.getExperimentalTopic());
    wordDataMap.put("recorder", userMapper.selectById(Long.parseLong(experimentalDataIndex.getRecorder())).getNickName());
    wordDataMap.put("major", experimentalDataIndex.getMajor());
    wordDataMap.put("classes", experimentalDataIndex.getClasses());
    wordDataMap.put("analyticalMethods", experimentalDataIndex.getAnalyticalMethods());
    wordDataMap.put("finishTime", experimentalDataIndex.getFinishTime());
    wordDataMap.put("experimentalIndicators", experimentalDataIndex.getExperimentalIndicators());
    wordDataMap.put("testConditions", experimentalDataIndex.getTestConditions());
    wordDataMap.put("experimentalScheme", experimentalDataIndex.getExperimentalScheme());
    // 实验附图
    List<ExperimentalDataImg> experimentalDataImgList = experimentalDataImgMapper.selectList(new
            LambdaQueryWrapper<ExperimentalDataImg>().eq(ExperimentalDataImg::getExperimentalId,
            experimentalDataIndex.getId()));

    // 附图导出封装类
    List<ExperimentalDataImgExportVo> imgExportVos = new ArrayList<>();

    int code = 1;
    for (ExperimentalDataImg experimentalDataImg : experimentalDataImgList) {
        ExperimentalDataImgExportVo experimentalDataImgExportVo = BaseDtoConvert.tToV(experimentalDataImg, ExperimentalDataImgExportVo.class);
        experimentalDataImgExportVo.setCode(code);
        if (StringUtils.isEmpty(experimentalDataImgExportVo.getRemarks())) {
            experimentalDataImgExportVo.setRemarks("无");
        }
        imgExportVos.add(experimentalDataImgExportVo);
        code++;
    }
    wordDataMap.put("experimentalImg", imgExportVos);
    wordDataMap.put("experimentalConclusion", experimentalDataIndex.getExperimentalConclusion());

    String downloadFileName =
            experimentalDataIndex.getExperimentalTopic() + System.currentTimeMillis() + ".docx";
    String savePath = filePath + downloadFileName;
    if (!FileUtil.exist(filePath)) {
        FileUtil.mkdir(filePath);
    }

    try {
        // 添加配置 循环表格行(实验附图)
        LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
        Configure config = Configure.builder()
                .bind("experimentalImg", policy).build();
        //渲染文件
        XWPFTemplate compile = XWPFTemplate.compile("./template/实验数据导出模板_template.docx", config);
        compile.render(wordDataMap);
        compile.writeToFile(savePath);
        this.httpDownload(response, request, downloadFileName, savePath);
    } catch (Exception e) {
        throw new ServiceException("下载实验数据失败!!" + e.getMessage());
    }
}

private void httpDownload(HttpServletResponse response, HttpServletRequest request,
                          String downloadFileName, String savePath) throws IOException {
    InputStream is = new FileInputStream(savePath);
    OutputStream os = response.getOutputStream();
    String userAgent = request.getHeader("user-agent").toLowerCase();
    if (userAgent.contains("msie") || userAgent.contains("like gecko")) {
        // win10 ie edge 浏览器 和其他系统的ie
        downloadFileName = URLEncoder.encode(downloadFileName, "UTF-8");
    } else {
        //其他的浏览器
        downloadFileName = new String(downloadFileName.getBytes(StandardCharsets.UTF_8),
                StandardCharsets.ISO_8859_1);
    }
    response.setContentType(FileSuffixConstants.DOC);
    response.setCharacterEncoding("UTF-8");
    response.setHeader("content-disposition",
            "attachment;filename=" + downloadFileName);
    response.setHeader("Access-Control-Expose-Headers", "content-disposition");
    IOUtils.copy(is, os);
    is.close();
    os.close();
    os.flush();
}

下载模板 :

下载效果:

docx

zip(包含两个测试文档)

踩过的坑:

1.poi-tl的依赖跟xalan.jar有冲突,同时存在会报错 

java.lang.IllegalArgumentException: 不支持:http://javax.xml.XMLConstants/property/accessExternalStylesheet

已知:poi-ti中已排除 xalan.jar

注:我的项目中引入的docx4j,docx4j中包含xalan.jar;删除docx4j相关依赖,不再报上述错误

2.poi-tl的版本号必须用最新版 (因为我需要在docx中插入图片,需要用到其附件功能)

否则会报错 Caused by: java.lang.NoSuchMethodError: org.apache.poi.xwpf.usermodel.XWPFRun.getFontSizeAsDouble()Ljava/lang/Double;
报的poi的方法找不到

最新版的poi-tl用的poi版本是:

我的工程中其他模块引入了poi-ooxml,所以也要对其做一个版本的升级

参考文档:Poi-tl Documentation 

以上,就是整个使用poi-tl导出docx文档的全部细节以及注意事项。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值