Java在导出excel时中添加图片导出

Java语言在导出excel功能中添加图片导出

使用到的工具类

java 复制代码
package com.test.util;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.ybbsy.travel.framework.common.util.http.HttpUtils;
import com.ybbsy.travel.framework.excel.core.handler.SelectSheetWriteHandler;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.multipart.MultipartFile;

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

/**
 * Excel 工具类
 *
 * @author 骑猪撞地球QAQ
 */
public class ExcelUtils {

    /**
     * 将列表以 Excel 响应给前端
     *
     * @param response  响应
     * @param filename  文件名
     * @param sheetName Excel sheet 名
     * @param head      Excel head 头
     * @param data      数据列表哦
     * @param <T>       泛型,保证 head 和 data 类型的一致性
     * @throws IOException 写入失败的情况
     */
    public static <T> void write(HttpServletResponse response, String filename, String sheetName,
                                 Class<T> head, List<T> data) throws IOException {
        // 输出 Excel
        EasyExcel.write(response.getOutputStream(), head)
                .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
                .registerWriteHandler(new SelectSheetWriteHandler(head)) // 基于固定 sheet 实现下拉框
                .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
                .sheet(sheetName).doWrite(data);
        // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了
        response.addHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(filename));
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
    }

    public static <T> List<T> read(MultipartFile file, Class<T> head) throws IOException {
        return EasyExcel.read(file.getInputStream(), head, null)
                .autoCloseStream(false)  // 不要自动关闭,交给 Servlet 自己处理
                .doReadAllSync();
    }
}
java 复制代码
// 导出 Excel
 ExcelUtils.write(response, "记录.xls", "数据", VO.class, list);

vo的图片类上面添加如下注解:

@ExcelProperty(value = "照片", converter = ImageConverter.class)

使用的是com.alibaba.excel.annotation.ExcelProperty;

java 复制代码
package com.test.convert;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ImageData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: 骑猪撞地球QAQ
 * @CreateTime: 2026-02-13
 * @Description: 图片转换器,将图片url转换为excel中的图片
 * @Version: 1.0
 */

public class ImageConverter implements Converter<String> {

    @Override
    public Class<String> supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.EMPTY;
    }

    @Override
    public WriteCellData<?> convertToExcelData(String urlStr, ExcelContentProperty contentProperty,
                                               GlobalConfiguration globalConfiguration) throws Exception {
        List<ImageData> imageDataList = new ArrayList<>();
        if (StrUtil.isEmpty(urlStr)) {
            return new WriteCellData<>(CellDataTypeEnum.STRING);
        }
        // url是用','分割的,进行切分;todo 此处可根据自己实际情况具体处理
        String[] urls = urlStr.split(",");
        for (String url : urls) {
            try (InputStream inputStream = new URL(url).openStream()) {
                // 原始图片读取
                BufferedImage srcImage = ImageIO.read(inputStream);
                // 预生成缩略图(提升性能)
                BufferedImage thumbnail = new BufferedImage(273, 89, BufferedImage.TYPE_INT_RGB);
                thumbnail.getGraphics().drawImage(
                        srcImage.getScaledInstance(273, 89, Image.SCALE_SMOOTH),
                        0, 0, null
                );
                // 转换为字节数组
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ImageIO.write(thumbnail, "JPEG", baos);
                ImageData imageData = new ImageData();
                imageData.setImage(baos.toByteArray());
                imageDataList.add(imageData);
            }
        }
        WriteCellData<?> cellData = new WriteCellData<>();
        if (!imageDataList.isEmpty()) {
            cellData.setImageDataList(imageDataList);
            cellData.setType(CellDataTypeEnum.EMPTY);
        } else {
            cellData.setStringValue("无图片");
            cellData.setType(CellDataTypeEnum.STRING);
        }
        return cellData;
    }
}
相关推荐
小羊没烦恼!5 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里5 天前
java中的继承和多态的区别
java
小羊没烦恼!5 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕5 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码6 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖6 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时6 天前
01-06-A-JVM排查实战详解
java·jvm
伞伞悦读6 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
vipxieliang6 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
C语言小火车6 天前
C/C++ 为什么需要编译器?
开发语言·c++