You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将Apache Poi Workbook注册为Spring IOC Bean时遇空文件异常的解决咨询

解决Spring IOC中Apache Poi Workbook Bean抛出EmptyFileException的问题

在将Apache Poi Workbook注册为Spring IOC管理的Bean时,抛出异常:

Caused by: org.apache.poi.EmptyFileException: The supplied file was empty (zero bytes long)

实际文件非空,且在非Spring管理的独立测试类中可正常创建Workbook实例。相关代码如下:

@Bean
public FileInputStream getInputStream() {
    try {
       return new FileInputStream(EXCEL_FILE_PATH);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    return null;
}

@Bean
public Workbook workbook()  {
    try {
        Workbook workbook = WorkbookFactory.create(getInputStream());
        getInputStream().close();
        return workbook;
    } catch (IOException e) {
        e.printStackTrace();
    }

    return null;
}

上述代码位于标注了@Configuration的配置类中。


问题原因分析

  1. 单例流的复用问题:getInputStream()被标记为@Bean,Spring会将其作为单例Bean缓存。流是有状态的资源,一旦被WorkbookFactory.create()读取完毕,指针会移动到文件末尾,后续复用该流时会读取到0字节。此外,代码中两次调用getInputStream(),第二次拿到的是同一个已被读取过的流,进一步加剧了问题。
  2. 路径问题导致流为null:若Spring环境中EXCEL_FILE_PATH对应的文件路径不正确(比如相对路径的基准目录与独立测试不同),会触发FileNotFoundException,此时getInputStream()返回null,而WorkbookFactory.create(null)会抛出EmptyFileException。
  3. 流关闭方式不当:手动关闭流容易出现重复关闭或未正确关闭的情况,且未处理流读取失败的异常传播。

解决方案

方案一:移除流的Bean注册,使用私有方法创建一次性流

将getInputStream()改为私有方法,避免Spring将其作为单例Bean管理,每次调用都创建新的流,并使用try-with-resources自动关闭流:

@Configuration
public class ExcelConfig {
    private static final String EXCEL_FILE_PATH = "你的文件绝对路径或正确的相对路径";

    private FileInputStream getInputStream() throws FileNotFoundException {
        return new FileInputStream(EXCEL_FILE_PATH);
    }

    @Bean
    public Workbook workbook() {
        try (FileInputStream inputStream = getInputStream()) {
            return WorkbookFactory.create(inputStream);
        } catch (IOException e) {
            throw new RuntimeException("创建Workbook失败", e);
        }
    }
}

方案二:直接在WorkBean方法中创建流(简化版)

省去单独的流方法,直接在workbook()中创建并使用流:

@Configuration
public class ExcelConfig {
    private static final String EXCEL_FILE_PATH = "你的文件路径";

    @Bean
    public Workbook workbook() {
        try (FileInputStream inputStream = new FileInputStream(EXCEL_FILE_PATH)) {
            return WorkbookFactory.create(inputStream);
        } catch (FileNotFoundException e) {
            throw new RuntimeException("未找到Excel文件:" + EXCEL_FILE_PATH, e);
        } catch (IOException e) {
            throw new RuntimeException("读取Excel文件失败", e);
        }
    }
}

方案三:使用Spring ResourceLoader解决路径问题

如果是路径问题导致的文件找不到,推荐使用Spring的ResourceLoader来安全加载文件,避免相对路径的歧义:

@Configuration
public class ExcelConfig {

    @Bean
    public Workbook workbook(ResourceLoader resourceLoader) {
        // 从类路径加载文件,适用于放在resources目录下的文件
        Resource resource = resourceLoader.getResource("classpath:excel/example.xlsx");
        try (InputStream inputStream = resource.getInputStream()) {
            return WorkbookFactory.create(inputStream);
        } catch (IOException e) {
            throw new RuntimeException("加载类路径下的Excel文件失败", e);
        }
    }
}

内容的提问来源于stack exchange,提问作者SimeonKV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:50:26