这几天客户提出了新的需求,要求记录要能够导出word,并且里面包含的图片也要导出来,这里借用EasyPOI来进行操作。

        参考文章:https://blog.csdn.net/qq_34752942/article/details/112203419

1、引入相关Jar包

        引入EasyPOI必要的Jar包,这里就不再多说,不知道引哪些的话请自行百度。

        注意:建议使用EasyPOI  4.3.0+ 版本的,因为word图片循环是4.3.0以后的版本才支持的。切记!!!

2、后台代码

2.1、导出对象类

        这里简单改造一个项目中使用的对象。关于照片的两个字段说明一下,这里是项目中图片上传到服务器之后,把图片在服务器的存储路径保存到数据库中,如果上传了多张图片,那么把就用逗号把路径拼接成一个字符串放入数据库。

public class ProblemRectify {

    /**
     * 标段名
     */
    private String bidName;       

    /**
     * 问题描述
     */
    private String description;

    /**
     * 问题照片,路径字符串,以逗号分隔
     */
    private String pictures;

    /**
     * 问题发现时间
     */
    private LocalDate checkDate;

    /**
     * 问题整改时限
     */
    private LocalDate rectifyDate;

    /**
     * 整改方案
     */
    private String rectifyPlan;

    /**
     * 整改结果
     */
    private String rectifyResult;

    /**
     * 整改后照片,路径字符串,以逗号分隔
     */
    private String rectifyPictures;

    /**
     * 整改完成时间
     */
    private LocalDate rectifyCompleteDate;

    /**
     * 整改状态
     */
    private String rectifyStatus;

    /**
     * 问题责任人名字
     */
    private String liablePersonName;

    /**
     * 问题发现人名字
     */
    private String findPersonName;

    /**
     * 问题类型
     */
    private String typeName;

    /**
     * 问题来源
     */
    private String sourceName;

    /**
     * 问题分类代码
     */
    private String sortName;

    /**
     * 问题级别代码
     */
    private String levelName;

    /**
     * 责任单位
     */
    private String proOrganizationName;

    /**
     * 所在桩号
     */
    private String pileNum;

}

2.2、Word模板

        要用EasyPOI的word模板导出,那么就要事先定义好word模板,并放入项目的指定位置。这里建议在resources下新建一个目录,我这里建的目录名是exportTemplate,大家可以根据实际需要自行创建。

        Word模板如下图所示:

       注意:关于EasyPOI模板指令的介绍,请参考EasyPOI的官网。仅说一下我在写word模板时遇到的问题:写表达式 {{属性名}}  时,不要有空格,然后就是在中文状态下输入{{和}},因为我切换到英文输入法输入时,表达式的值没法被值替换掉。

2.3、核心代码

         Map<String,Object> params  是word模板导出时,用来装要导出的数据。需要注意的是,构造Map时,注意字段值的判空。由于文件是先按模板生成再下载,所以会生成一个临时的文件在指定位置,如果不需要的话,那就在文件下载之后将其删除。

void testExportData() {

        // 从数据库根据id获取数据,这里id我用了一个写死的,具体项目中,id请通过前端传入
        ProblemRectify rectifyInfo = problemRectifyService.getCheckRectifyInfo(131L);
        // 构造导出数据
        Map<String, Object> exportParams = new HashMap<>();
        exportParams.put("description", rectifyInfo.getDescription());
        exportParams.put("bidName", rectifyInfo.getBidName());
        exportParams.put("pileNum", rectifyInfo.getPileNum());
        exportParams.put("sourceName",rectifyInfo.getSourceName());
        exportParams.put("levelName",rectifyInfo.getLevelName());
        exportParams.put("typeName",rectifyInfo.getTypeName());
        exportParams.put("sortName",rectifyInfo.getSortName());
        
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
     exportParams.put("checkDate",rectifyInfo.getCheckDate().format(dateTimeFormatter));
        
 exportParams.put("rectifyDate",rectifyInfo.getRectifyDate().format(dateTimeFormatter));
 exportParams.put("proOrganizationName",rectifyInfo.getProOrganizationName()));
        exportParams.put("findPersonName",rectifyInfo.getFindPersonName());
        exportParams.put("liablePersonName",rectifyInfo.getLiablePersonName());
        exportParams.put("rectifyStatus",rectifyInfo.getRectifyStatus());
        exportParams.put("rectifyCompleteDate",rectifyInfo.getRectifyCompleteDate().format(dateTimeFormatter));
        exportParams.put("rectifyPlan", StringUtils.isNotBlank(rectifyInfo.getRectifyPlan()) ? checkRectifyInfo.getRectifyPlan() : "无整改方案");
        exportParams.put("rectifyResult",StringUtils.isNotBlank(checkRectifyInfo.getRectifyResult()) ? rectifyInfo.getRectifyResult() : "无整改结果");

        // 整改前照片
        String picturePathStr = rectifyInfo.getPictures();
        List<ImageEntity> pictureImageList = initImageData(picturePathStr);
        exportParams.put("pictures",pictureImageList);
        // 整改后照片
        String rectifyPicturesPathStr = checkRectifyInfo.getRectifyPictures();
        List<ImageEntity> rectifyImageList = initImageData(rectifyPicturesPathStr);
        exportParams.put("rectifyImages",rectifyImageList);


        this.exportWord("exportTemplate/problemExportTemplate.docx","问题详情.docx",exportParams);
        System.out.println("文件导出成功!");
    }
    /****
     * 导出word数据
     * @param templatePath
     * @param fileName
     * @param params
     */
    private void exportWord(String templatePath, String fileName, Map<String, Object> params) {
        Assert.notNull(templatePath, "模板路径不能为空!");
        Assert.notNull(fileName, "文件名称不能为空!");
        Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式!");
        try {
            XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params);
            String tempPath = fileName;
            FileOutputStream fos = new FileOutputStream(tempPath);
            doc.write(fos);
            // 设置强制下载不打开
            response.setContentType("application/force-download");
            // 设置文件名
            response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName,"UTF-8"));
            OutputStream out = response.getOutputStream();
            doc.write(out);
            out.close();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            delFileWord(tempPath,fileName);
        }
    }

    private List<ImageEntity> initImageData(String fileUrl) {
        List<ImageEntity> result = new ArrayList<>();
        if (StringUtils.isNotBlank(fileUrl)) {
            if (fileUrl.indexOf(",") > 0) {
                String[] fileUrlArr = fileUrl.split(",");
                for (int i = 0 ; i < fileUrlArr.length ; i++) {
                    byte[] imageData = FDSUtils.downloadFile(fileUrlArr[i]);
                    ImageEntity item = new ImageEntity();
                    item.setWidth(300);
                    item.setHeight(300);
                    item.setData(imageData);
                    item.setType(ImageEntity.Data);
                    result.add(item);
                }
            } else {
                byte[] imageData = FDSUtils.downloadFile(fileUrl);
                ImageEntity item = new ImageEntity();
                item.setWidth(300);
                item.setHeight(300);
                item.setData(imageData);
                item.setType(ImageEntity.Data);
                result.add(item);
            }
        } else {
            ImageEntity item = new ImageEntity();
            item.setWidth(300);
            item.setHeight(300);
            item.setData(null);
            item.setType(ImageEntity.Data);
            result.add(item);
        }
        return result;
    }

    /***
     * 删除临时文件
     * @param filePath
     * @param fileName
     */
    private static void delFileWord(String filePath, String fileName){
        File file =new File(filePath+fileName);
        File file1 =new File(filePath);
        file.delete();
        file1.delete();
    }

        注意:这里代码需要注意的两个地方,一是模板路径,二是图片的设置,我这里是通过图片路径获取图片的byte[ ]数据,也就是代码中的fastDFSUtils.downloadFile(fileUrl)。因为项目中使用的fastDFS进行文件的上传和存储,写的有这个工具类。

        但是,如果不想通过这种方法,也可以直接使用图片Url的方式,利用ImageEntity下的setUrl方法设置图片的存储的路径,然后通过setType将类型设置为ImageEntity.Url,这种方法我没有测试,大家可以测试一下。

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐