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

Java Spring Boot:WebClient内存下载XLS及对象转换问题

使用Spring WebFlux WebClient内存下载并读取XLS文件

问题分析

你之前遇到的UnsupportedMediaTypeException,核心原因有两个:

  • 错误设置了请求头Content-Type:这个头用于标识请求体的类型,而GET请求无需设置;你应该通过accept方法告知WebClient可接受的响应类型。
  • 服务器返回的Content-Type存在不一致(错误提示为text/xml,但Postman显示是application/vnd.ms-excel),需要让WebClient忽略这种不匹配,强制处理响应体。

解决方案

方法1:直接获取字节数组(与RestTemplate逻辑一致)

直接将响应体转换为byte[],这是WebClient原生支持的类型,无需额外配置:

byte[] fileBytes = webClientBuilder.build().get()
        .uri(xlsLink)
        .accept(MediaType.parseMediaType("application/vnd.ms-excel")) // 指定接受的响应类型
        .retrieve()
        .bodyToMono(byte[].class)
        .block(); // 非阻塞场景可改用subscribe,此处用block实现同步获取结果

方法2:使用ByteArrayResource

如果需要用ByteArrayResource,可通过exchangeToMono手动处理响应体:

ByteArrayResource xlsResource = webClientBuilder.build().get()
        .uri(xlsLink)
        .accept(MediaType.parseMediaType("application/vnd.ms-excel"))
        .exchangeToMono(response -> {
            // 读取响应体为字节数组后包装成ByteArrayResource
            return response.bodyToMono(byte[].class)
                    .map(bytes -> new ByteArrayResource(bytes));
        })
        .block();

内存中读取XLS内容示例(基于Apache POI)

拿到字节数组后,可使用Apache POI在内存中解析XLS,无需保存到磁盘:

<!-- Maven依赖 -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.2.5</version>
</dependency>

解析代码:

try (InputStream inputStream = new ByteArrayInputStream(fileBytes);
     HSSFWorkbook workbook = new HSSFWorkbook(inputStream)) {
    // 获取第一个工作表
    HSSFSheet sheet = workbook.getSheetAt(0);
    // 遍历行与单元格,打印内容
    for (Row row : sheet) {
        for (Cell cell : row) {
            String cellValue;
            switch (cell.getCellType()) {
                case STRING:
                    cellValue = cell.getStringCellValue();
                    break;
                case NUMERIC:
                    cellValue = DateUtil.isCellDateFormatted(cell)
                            ? cell.getDateCellValue().toString()
                            : String.valueOf(cell.getNumericCellValue());
                    break;
                case BOOLEAN:
                    cellValue = String.valueOf(cell.getBooleanCellValue());
                    break;
                default:
                    cellValue = "";
            }
            System.out.print(cellValue + "\t");
        }
        System.out.println();
    }
} catch (IOException e) {
    e.printStackTrace();
}

关键注意点

  • 不要设置多余请求头:GET请求无需Content-Type和Content-Disposition请求头,这些属于响应头范畴。
  • 非阻塞场景优先用subscribe:在WebFlux的非阻塞环境中,尽量避免调用block(),改用响应式方式处理结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 18:55:33