EasyExcel导入导出功能中的图片读取和写入

在平时的开发中,经常需要处理Excel的导入导出功能。一般使用poi或EasyExcel进行开发,使用poi处理Excel相对较为复杂,而大部分开发者会选择EasyExcel,因为仅需一行代码就能实现导入和导出的功能。然而,EasyExcel不支持图片的读取操作,因此本文将介绍如何实现图片的读取和写入功能。

EasyExcel官网的常见问题中指出,EasyExcel目前不支持读取图片的功能。

读取图片

poi支持图片的读取。我们可以使用poi编写一个工具类,以支持图片的读取。首先需要添加maven依赖,EasyExcel已经包含poi依赖,因此无需额外添加poi依赖:

<!-- easyexcel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.0.5</version>
</dependency>
<dependency>
    <groupId>net.sf.jxls</groupId>
    <artifactId>jxls-core</artifactId>
    <version>1.0.6</version>
</dependency>

图片的读取核心代码如下:

Workbook workbook = WorkbookFactory.create(inputStream);
// 默认读取第一页
XSSFSheet sheet = (XSSFSheet) workbook.getSheetAt(0);
List<POIXMLDocumentPart> documentPartList = sheet.getRelations();
for (POIXMLDocumentPart part : documentPartList) {
    if (part instanceof XSSFDrawing) {
        XSSFDrawing drawing = (XSSFDrawing) part;
        List<XSSFShape> shapes = drawing.getShapes();
        for (XSSFShape shape : shapes) {
            XSSFPicture picture = (XSSFPicture) shape;
            XSSFClientAnchor anchor = picture.getPreferredSize();
            CTMarker marker = anchor.getFrom();
            int row = marker.getRow();
            int col = marker.getCol();
            // 从第2行开始
            if (row > 0 && row <= size) {
                PictureData pictureData = picture.getPictureData();
                String extension = pictureData.suggestFileExtension();
                byte[] bytes = pictureData.getData();
             }
        }
    }
}    

图片读取流程:

  • 首先要获取第一页(sheet)数据 workbook.getSheetAt(0)
  • 遍历 sheet.getRelations() 提取XSSFDrawing,即图片数据。
  • 遍历每行数据,获取字节流。

在将代码复制到IDE中时,可能会提示某些方法不存在,这时需要核对poi的版本。上述引用的EasyExcel版本为3.0.5,其中包含的poi版本是4.1.2。

封装工具类

通过上述代码,我们可以获取到图片的字节流,然后对字节流进行上传或存储处理。但是,每次读取都需要重复编写代码,这样会使代码显得冗余。因此,我们需要将上述代码封装成一个工具类。

例如,如果要上传一个文件,需要将数据赋值给两个字段name和imageStr:

@ExcelProperty("姓名")
private String name;

@ExcelProperty(value = "图片")
private String imageStr;

首先配置一个ExcelImageProperty注解,确定哪一列的图片需要赋值给对应的图片字段:

@Inherited
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelImageProperty {

    String[] value() default {""};

    /**
     * 图片在第几列 1开始
     * @return
     */
    int index() default -1;
}

imageStr对应第二列,字段上ExcelImageProperty注解的

index = 2

,上述实体修改如下:

@ExcelProperty("姓名")
private String name;

@ExcelProperty(value = "图片")
@ExcelImageProperty(index = 2)
private String imageStr;

在编写好实体和注解后,再编写一个工具类。

@Slf4j
public class ExcelReadImageUtil {
    ...
}

传入一个列表,通过获取读取输入流获取到图片,并赋值给对应的字段。

  • 此模板是一个列表模板,不支持自定义模板。
  • 使用poi读取图片,第二行读取数据,遍历每列数据,符合注解字段就赋值。一般获取到输入流后会上传图片,返回一个地址,这里仅仅获取字节流,赋值给对应的字段。

使用EasyExcel读取非图片数据和工具类读取图片数据:

InputStream inputStream = multipartFile.getInputStream();
List<DemoExcelInput> demoExcelInputs = EasyExcelFactory.read(multipartFile.getInputStream()).head(DemoExcelInput.class).sheet().doReadSync();
ExcelReadImageUtil.readImage(inputStream,demoExcelInputs);


注意:

inputStream不能重复使用,否则会报错

inputStream close

错误。

写图片

EasyExcel支持多种格式的写图片,包括:

  • URL
  • InputStream
  • byte[]
  • File
  • 自定义转换器

添加写的实体:

@Data
public class DemoExcelInput {
    ...
}

读取图片:

...

导出文件截图:

但是上述imageStr对应的String类型EasyExcel并不支持,但却能导出图片,这就需要使用到自定义转换器。

创建ExcelUrlImageConverter转换器:

...

将读取到的图片流转换为WriteCellData对象,从而实现图片的写入。

未经允许不得转载:大白鲨游戏网 » EasyExcel导入导出功能中的图片读取和写入