利用EasyPOI导出Excel,内容中含有图片

需求背景

做一个OCR识别的功能,需要导出原图和识别出来的结果的图纸,将数据导出.

解决方案

EasyPOI中可以用字节类型,导出图片,可以将图片存放的url 转成字节,然后导出.但是整个导出过程耗时较久。

具体代码

/**
     * 草图OCR识别记录-导出.
     *
     * @param response:     HttpServletResponse.
     * @param pageQueryBO:筛选条件.
     */
    @RequestMapping(value = "/exportExcel", method = RequestMethod.POST)
    public ResponseEntity<ByteArrayResource> exportExcel(@RequestBody BuOrcPicOssRecordPageQueryBO pageQueryBO, HttpServletResponse response) throws IOException {
        //导出数据
        List<BuOrcPicOssRecordExportBO> list = new ArrayList<>();
        // 导出的数据不需要分页
        pageQueryBO.setNoNeedPaging(true);

        ResultBO<PageBO<List<BuOrcPicOssRecordBO>>> pageBOResultBO = buOrcPicOssRecordService.selectOrcPicOssRecordPageList(pageQueryBO);
        List<BuOrcPicOssRecordBO> dataList = pageBOResultBO.getData().getDataList();
        if(ObjectUtils.isNotEmpty(dataList)){
            list = ModelMapperUtil.mapList(dataList,BuOrcPicOssRecordExportBO.class);
        }

        // 导出原先的图片和识别后的图片
        BASE64Decoder base64Decoder = new BASE64Decoder();
        // 解码操作
        for(BuOrcPicOssRecordExportBO item:list ){

            // Base64 转字节流显示图片
            if(ObjectUtils.isNotEmpty(item.getRoofPicUrl())){
                byte[] bytes = base64Decoder.decodeBuffer(item.getRoofPicUrl().replace("data:image/png;base64,",""));
                item.setRoofPicFile(bytes);
            }

            // url转字节流显示图片

            if(ObjectUtils.isNotEmpty(item.getPicOssUrl())){
                byte[] netImgByUrl = ImageUtil.getNetImgByUrl(item.getPicOssUrl());
                item.setPicOssFile(netImgByUrl);
            }

        }

        //.xlsx格式
        //response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        //.xls格式
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        //前端存在跨域不成功,设置可访问
        response.setHeader("Access-Control-Allow-Origin","*");
        //设置不要缓存
        response.setHeader("Pragma", "No-cache");
        try {

            // 自定义参数-数据行数,下面判断使用.
            int listCount =0;
            // 循环设置行高
            if(!list.isEmpty()){
                listCount = list.size();
            }

            // 这里URLEncoder.encode可以防止中文乱码
            String fileName = URLEncoder.encode("草图OCR识别记录", String.valueOf(StandardCharsets.UTF_8));
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");
            //设置sheet名
            ExportParams params = new ExportParams();
            params.setSheetName("草图OCR识别记录");
            //设置标题
            params.setTitle("草图OCR识别记录");
            // 这里需要设置不关闭流
            Workbook workbook = ExcelExportUtil.exportExcel(params, BuOrcPicOssRecordExportBO.class, list);

            // 如果有内容,则循环赋值行高
            if(listCount>0){
                Sheet sheet0 = workbook.getSheet("草图OCR识别记录");
                for (int i=2;i<listCount+2;i++){
                    sheet0.getRow(i).setHeight((short)4000);
                }
            }

            //输出流
            OutputStream outStream = response.getOutputStream();
            //浏览器下载
            workbook.write(outStream);

            ByteArrayResource byteArrayResource = convertOutputStreamToResource(outStream);

            return ResponseEntity.ok().body(byteArrayResource);

        } catch (IOException e) {

            return  ResponseEntity.status(500).body(null);
        }
    }



    /**
     * 转换方法 必须得用 public访问.
     *
     * @param outputStream
     * @return
     * @throws IOException
     */
    public static ByteArrayResource convertOutputStreamToResource(OutputStream outputStream) throws IOException {
        // 使用ByteArrayOutputStream来捕获OutputStream的输出
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        // 将原始OutputStream的内容复制到ByteArrayOutputStream中
        // 注意:这里假设你有一个方法可以将数据写入outputStream,这里用writeData作为示例
        // writeData(outputStream); // 这应该是一个你自定义的方法,用于将数据写入outputStream

        // 由于我们不能直接操作原始的outputStream(因为它是只写的,并且数据已经写入),
        // 我们假设上面的writeData方法实际上是将数据写入了一个我们可以控制的OutputStream,
        // 或者我们在这里模拟写入一些数据到byteArrayOutputStream中。
        // 在实际情况中,你需要将你的数据写入byteArrayOutputStream。

        // 为了示例,我们直接往byteArrayOutputStream中写一些数据:
        String exampleData = "This is some example data that will be in the Excel file.";
        byteArrayOutputStream.write(exampleData.getBytes());

        // 获取字节数组
        byte[] data = byteArrayOutputStream.toByteArray();

        // 创建ByteArrayResource
        ByteArrayResource resource = new ByteArrayResource(data);

        // 返回Resource
        return resource;
    }

导出的参数类

@ExcelTarget(value = "草图OCR识别记录")
@Data
public class BuOrcPicOssRecordExportBO {

    /**
     * ltc代理商名称
     */
    @Excel(name = "代理商名称", width = 20)
    @ContentFontStyle(fontHeightInPoints = 20) // 设置字体大小为20来增加行高
    private String ltcAgentName;

    /**
     * 创建人名称
     */
    @Excel(name = "创建人", width = 20)
    private String creatorName;

    /**
     * 创建时间
     */
    @Excel(name = "创建时间", width = 20, exportFormat = "yyyy-MM-dd HH:mm:ss")
    private Date gmtCreate;

    /**
     * 图片在oss的路径
     */
    private String picOssUrl;

    /**
     * Excel里面显示图片
     */
    @Excel(name = "上传图片", type = 2, width = 60, imageType = 2 )
    private byte[] picOssFile;

    /**
     * 识别成的屋面图形图片Base64
     */
    private String roofPicUrl;

    /**
     * Excel里面显示图片
     */
    @Excel(name = "识别后屋面图片", type = 2, width = 60, imageType = 2 )
    private byte[] roofPicFile;

    /**
     * 评价的等级名称
     */
    @Excel(name = "评价", width = 20)
    private String evaluateLevelName;

    /**
     * 评价的途径名称
     */
    @Excel(name = "评价途径", width = 20)
    private String evaluateWayName;

    /**
     * 评价进度状态 0:未读未评价 1:已读未评价  10:已经评价完成
     *
     * @see com.chintanneng.ai.enums.EvaluateStateEnum
     */
    private Integer evaluateState;

    /**
     * 图纸/电站id
     */
    private Long powerStationId;

    /**
     * 虚拟电站编码
     */
    private String powerStationCode;

    /**
     * 电站编码-实际电站编码
     */
    @Excel(name = "电站编码", width = 20)
    private String powerStationRealCode;


    /**
     * 点评人姓名
     */
    @Excel(name = "点评人", width = 20)
    private String evaluateUserFullName;

    /**
     * 点评时间
     */
    @Excel(name = "点评时间", width = 20, exportFormat = "yyyy-MM-dd HH:mm:ss")
    private Date evaluateTime;

}

ImageUtil 里面的方法

    /**
     * 获取网络图片转成字节流
     * @param strUrl 完整图片地址
     * @return 图片资源数组
     */
    public static byte[] getNetImgByUrl(String strUrl) {
        try {
            URL url = new URL(strUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(2 * 1000);
            // 通过输入流获取图片数据
            InputStream inStream = conn.getInputStream();
            // 得到图片的二进制数据
            byte[] btImg = readInputStream(inStream);
            return btImg;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码写到35岁

你的鼓励将是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值