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

Spring MVC如何返回含二进制字段的DeviceSummaryResponse对象

问题与解决方案:Spring MVC返回含二进制文件字段的响应转换器错误

问题场景

定义了如下DeviceSummaryResponse类,其中route字段为InputStream类型,用于存储GPX文件流:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class DeviceSummaryResponse {

    @ApiModelProperty(value = "Конфигурация устройства", required = true)
    private ConfigResponse config;

    @ApiModelProperty(value = "GPX файл с маршрутом устройства", required = true)
    private InputStream route;
}

通过Spring MVC接口返回该对象时,因route字段无法被默认消息转换器处理,出现转换器错误。需符合OpenAPI规范中route字段为string格式binary的要求:

DeviceSummaryResponse:
      type: object
      properties:
        config:
          type: object
          properties:
           ...
          ...
        route:
          type: string
          format: binary
          description: GPX файл с маршрутом устройства
      required:
        - config
        - route

解决方案

方案1:将InputStream转为Base64编码字符串

OpenAPI中的string/binary格式对应Base64编码的二进制内容,因此可以将InputStream读取为字节数组后转为Base64字符串,修改响应类并完成映射:

  1. 修改DeviceSummaryResponse类,将route字段类型改为String,并指定ApiModelProperty的格式:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class DeviceSummaryResponse {

    @ApiModelProperty(value = "Конфигурация устройства", required = true)
    private ConfigResponse config;

    @ApiModelProperty(value = "GPX файл с маршрутом устройства", required = true, dataType = "string", format = "binary")
    private String route;
}
  1. 在对象映射时,读取InputStream内容并转为Base64字符串:
public DeviceSummaryResponse toResponse(DeviceSummary deviceSummary) {
    // 读取输入流为字节数组(可使用Apache Commons IO的IOUtils,或自行实现流读取)
    byte[] routeBytes;
    try (InputStream inputStream = deviceSummary.getRoute()) {
        routeBytes = IOUtils.toByteArray(inputStream);
    } catch (IOException e) {
        throw new RuntimeException("Ошибка чтения потока маршрута", e);
    }
    // 转为Base64编码字符串
    String base64Route = Base64.getEncoder().encodeToString(routeBytes);
    
    return DeviceSummaryResponse.builder()
            .config(configMapper.toResponse(deviceSummary.getConfig()))
            .route(base64Route)
            .build();
}
  1. 原接口无需修改,Spring会自动将String类型的route序列化为JSON字符串,符合OpenAPI规范要求。

补充说明

  • Spring默认的JSON消息转换器无法直接序列化InputStream,转为Base64字符串后可被正常序列化。
  • 使用try-with-resources确保输入流被正确关闭,避免资源泄漏。
  • 若不依赖Apache Commons IO,可自行实现流读取逻辑:
private byte[] readInputStream(InputStream is) throws IOException {
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    int bytesRead;
    byte[] data = new byte[1024];
    while ((bytesRead = is.read(data, 0, data.length)) != -1) {
        buffer.write(data, 0, bytesRead);
    }
    buffer.flush();
    return buffer.toByteArray();
}

内容的提问来源于stack exchange,提问作者Шатов Данил

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:43:26