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字符串,修改响应类并完成映射:
- 修改
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; }
- 在对象映射时,读取
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(); }
- 原接口无需修改,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,提问作者Шатов Данил
相关产品推荐
相关产品推荐

