EasyExcel 导出包含图片的 Excel 文件

使用 EasyExcel 导出包含图片的 Excel 文件

在开发中,我们经常需要导出 Excel 文件以便生成报表、清单等数据展示,包含图片的 Excel 文件尤其常见。EasyExcel 是阿里巴巴开源的一个高效、易用的 Excel 读写框架,它在性能和内存占用上比 Apache POI 表现更优。但默认情况下,EasyExcel 并不支持从网络下载图片导出到 Excel,需要我们进行一些额外的处理。本文将介绍如何使用 EasyExcel 导出包含图片的 Excel 文件,并处理图片源为网络 URL 的情况。

一、背景需求

假设我们在一个电商系统中,需要批量导出商品清单,并包含商品的基本信息和图片。商品图片有时存储在云存储中(例如腾讯云或阿里云),我们在数据库中只存储图片的 URL。在导出 Excel 时,我们需要将这些图片下载并写入 Excel 文件中相应的商品条目。

二、实现步骤
  1. 创建商品数据类:定义包含图片的 Excel 数据实体类。
  2. 实现图片下载方法:创建工具方法,将网络图片下载为字节数组。
  3. 使用 EasyExcel 导出 Excel:将数据实体类列表导出为 Excel 文件,并处理图片字段。

接下来,让我们逐步实现这一功能。

三、创建商品数据类

首先,我们创建一个 ExcelGoodsVo 类来存放导出 Excel 时的商品数据。使用 @ExcelProperty 注解指定字段对应的 Excel 列,并将图片字段定义为 byte[] 类型。

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;

public class ExcelGoodsVo {
    
    
    @ExcelProperty("商品名称")
    private String name;

    @ExcelProperty("分类")
    private String categoryName;

    @ExcelProperty("价格")
    private Double price;

    @ExcelProperty("库存")
    private Integer stock;

    @ExcelProperty("描述")
    private String des;

    @ExcelProperty("图片")
    @ColumnWidth(20) // 设置列宽以适应图片显示
    private byte[] picture; // 图片字节数组

    // getters 和 setters
}
四、实现网络图片下载方法

我们创建一个通用方法 downloadImage,该方法接受图片 URL,通过 HTTP 请求下载图片,将其转换为字节数组后返回。这样,我们可以将 URL 图片下载至本地,并在 EasyExcel 写入时直接使用字节数组作为图片数据。

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.IOException;

public class ImageDownloadUtil {
    
    
    
    public static byte[] downloadImage(String urlString) throws IOException {
    
    
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(5000); // 设置连接超时
        connection.setReadTimeout(5000);    // 设置读取超时

        try (InputStream inputStream = connection.getInputStream();
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
    
    
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
    
    
                outputStream.write(buffer, 0, bytesRead);
            }
            return outputStream.toByteArray();
        }
    }
}
五、使用 EasyExcel 导出包含图片的 Excel

在主业务逻辑中,我们会加载商品信息,并对图片 URL 进行处理,将图片字节数据设置到实体类中。以下是使用 EasyExcel 导出商品清单的实现。

import org.springframework.http.ResponseEntity;
import java.util.List;
import java.util.stream.Collectors;

public class GoodsService {
    
    

    public ResponseEntity<byte[]> exportGoodsList(GoodsDto goodsDto) {
    
    
        Goods goods = MappingUtil.mapObject(goodsDto, Goods.class);

        // 根据条件获取商品信息
        List<ExcelGoodsVo> excelGoodsVoList = goodsMapper.findAll(goods).stream().map(goods1 -> {
    
    
            ExcelGoodsVo excelGoodsVo = new ExcelGoodsVo();
            excelGoodsVo.setName(goods1.getName());
            excelGoodsVo.setPrice(goods1.getPrice());
            excelGoodsVo.setStock(goods1.getStock());
            excelGoodsVo.setCategoryName(categoryMapper.findById(goods1.getCategoryId()).getName());
            excelGoodsVo.setDes(goods1.getDesc());

            // 图片处理
            try {
    
    
                byte[] imageBytes = ImageDownloadUtil.downloadImage(goods1.getPictureUrl());
                excelGoodsVo.setPicture(imageBytes);
            } catch (IOException e) {
    
    
                log.error("商品图片读取失败!", e);
                throw new RuntimeException("商品图片读取失败!", e);
            }
            return excelGoodsVo;
        }).collect(Collectors.toList());

        // 导出 Excel 文件
        return ExcelUtil.exportToExcel(excelGoodsVoList, "goodsList.xlsx", ExcelGoodsVo.class);
    }
}
六、导出 Excel 工具类实现

我们可以使用 EasyExcel 工具类 ExcelUtil 简化 Excel 导出过程。此方法会将数据写入到 Excel,并将结果作为字节数组返回,便于直接在 Web 环境中输出。

import com.alibaba.excel.EasyExcel;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;

public class ExcelUtil {
    
    

    public static <T> ResponseEntity<byte[]> exportToExcel(List<T> data, String fileName, Class<T> clazz) {
    
    
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
    
    
            EasyExcel.write(outputStream, clazz).sheet("Sheet1").doWrite(data);
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", "attachment; filename=" + fileName);
            return new ResponseEntity<>(outputStream.toByteArray(), headers, HttpStatus.OK);
        } catch (IOException e) {
    
    
            throw new RuntimeException("Excel 导出失败", e);
        }
    }
}
七、测试和结果

通过运行 exportGoodsList() 方法,将会生成一个包含图片的商品 Excel 文件,用户可以直接下载。此 Excel 文件将包含商品的名称、分类、价格、库存、描述以及图片字段的内容。

八、注意事项
  1. 图片下载延迟:如果网络不佳,下载多个图片可能耗时较长,建议在图片下载前设置合理的连接超时和读取超时。
  2. 图片大小控制:考虑到文件大小问题,导出大量图片时应当优化图片格式或压缩图片。
  3. 错误处理:如遇到网络问题或图片无法访问,建议记录日志,并用默认图片或空白图片填充,避免程序崩溃。
九、总结

使用 EasyExcel 导出包含图片的 Excel 文件,为我们实现更加丰富的 Excel 报表提供了便利。通过自定义方法从网络下载图片并将其转换为字节数组,可以轻松地将远程图片插入到 Excel 中。这种方法不仅适用于电商商品导出,还可应用于任意需要在 Excel 中展示图片的场景。希望本文对您实现导出包含图片的 Excel 有所帮助。

猜你喜欢

转载自blog.csdn.net/qq_56694800/article/details/143240634