如何让Spring WebClient将application/dicom视为octet-stream解析多部件响应
我之前处理过类似的场景,Spring WebClient 默认的 multipart 编解码器并不会自动把 application/dicom 类型的部件识别为 FilePart——它只对常见的文件类型比如 application/octet-stream 等提供支持。要实现你的需求,核心是扩展默认的编解码器,让它把 application/dicom 当作文件类型来处理,下面给你两种可行的方案:
方案一:全局配置WebClient的编解码器
如果你希望所有WebClient请求都支持处理 application/dicom 类型的multipart部件,可以在配置WebClient Bean的时候自定义编解码器:
@Bean public WebClient webClient() { return WebClient.builder() .exchangeStrategies(strategies -> strategies.codecs(configurer -> { // 自定义PartHttpMessageReader,扩展支持application/dicom DefaultPartHttpMessageReader customPartReader = new DefaultPartHttpMessageReader() { @Override protected boolean supportsMediaType(MediaType mediaType) { // 保留原有支持的媒体类型,同时添加对application/dicom的支持 return super.supportsMediaType(mediaType) || MediaType.valueOf("application/dicom").isCompatibleWith(mediaType); } }; // 替换默认的MultipartHttpMessageReader,使用自定义的PartReader configurer.defaultCodecs().multipartReader(new MultipartHttpMessageReader(customPartReader)); })) .build(); }
这样配置后,你的原有 getDicoms 方法不需要修改,WebClient会自动把 application/dicom 类型的multipart部件解析为 FilePart。
方案二:针对单个请求配置编解码器
如果只需要在这个特定的请求中支持 application/dicom,可以在请求内单独指定ExchangeStrategies:
public Flux<FilePart> getDicoms(String seriesUri) { // 构建自定义的ExchangeStrategies ExchangeStrategies customStrategies = ExchangeStrategies.builder() .codecs(configurer -> { DefaultPartHttpMessageReader customPartReader = new DefaultPartHttpMessageReader() { @Override protected boolean supportsMediaType(MediaType mediaType) { return super.supportsMediaType(mediaType) || MediaType.valueOf("application/dicom").equals(mediaType); } }; configurer.defaultCodecs().multipartReader(new MultipartHttpMessageReader(customPartReader)); }) .build(); return webClient.get() .uri(seriesUri) .accept(MediaType.ALL) .exchangeStrategies(customStrategies) // 应用自定义策略 .retrieve() .bodyToFlux(FilePart.class); }
原理说明
DefaultPartHttpMessageReader 是Spring处理multipart部件的核心类,它默认只支持有限的媒体类型(比如 application/octet-stream、text/plain 等)。我们通过重写它的 supportsMediaType 方法,把 application/dicom 加入到支持列表中,这样Multipart编解码器就会把该类型的部件当作普通文件部件处理,最终解析为 FilePart 对象。
需要注意的是,如果你的multipart部件包含 filename 参数,FilePart 会自动获取到文件名;如果没有,你可能需要通过 Part 的元数据自行处理,但一般多文件下载的multipart响应都会包含这个参数。
内容的提问来源于stack exchange,提问作者Saveriu CIANELLI

