使用 EasyExcel 导出包含图片的 Excel 文件
在开发中,我们经常需要导出 Excel 文件以便生成报表、清单等数据展示,包含图片的 Excel 文件尤其常见。EasyExcel 是阿里巴巴开源的一个高效、易用的 Excel 读写框架,它在性能和内存占用上比 Apache POI 表现更优。但默认情况下,EasyExcel 并不支持从网络下载图片导出到 Excel,需要我们进行一些额外的处理。本文将介绍如何使用 EasyExcel 导出包含图片的 Excel 文件,并处理图片源为网络 URL 的情况。
目录
一、背景需求
假设我们在一个电商系统中,需要批量导出商品清单,并包含商品的基本信息和图片。商品图片有时存储在云存储中(例如腾讯云或阿里云),我们在数据库中只存储图片的 URL。在导出 Excel 时,我们需要将这些图片下载并写入 Excel 文件中相应的商品条目。
二、实现步骤
- 创建商品数据类:定义包含图片的 Excel 数据实体类。
- 实现图片下载方法:创建工具方法,将网络图片下载为字节数组。
- 使用 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 文件将包含商品的名称、分类、价格、库存、描述以及图片字段的内容。
八、注意事项
- 图片下载延迟:如果网络不佳,下载多个图片可能耗时较长,建议在图片下载前设置合理的连接超时和读取超时。
- 图片大小控制:考虑到文件大小问题,导出大量图片时应当优化图片格式或压缩图片。
- 错误处理:如遇到网络问题或图片无法访问,建议记录日志,并用默认图片或空白图片填充,避免程序崩溃。
九、总结
使用 EasyExcel 导出包含图片的 Excel 文件,为我们实现更加丰富的 Excel 报表提供了便利。通过自定义方法从网络下载图片并将其转换为字节数组,可以轻松地将远程图片插入到 Excel 中。这种方法不仅适用于电商商品导出,还可应用于任意需要在 Excel 中展示图片的场景。希望本文对您实现导出包含图片的 Excel 有所帮助。