如何在Spring中实现流式返回多个不同MIME类型的multipart消息
手动拼接边界、构造多部分内容的方式容易出现换行符不规范、boundary冲突、不符合RFC标准等问题,Spring 原生提供了多部分响应的构造支持,不需要手动处理任何边界相关逻辑,核心依赖MultipartBodyBuilder实现,改造后的代码如下:
import org.springframework.http.MultipartBodyBuilder; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.Executor; @GetMapping(value = "/data", produces = MediaType.MULTIPART_RELATED_VALUE) public ResponseEntity<ResponseBodyEmitter> streamMultipart() { // 省略实际内容获取逻辑 InputStream audio = new ByteArrayInputStream(null); // 异步获取的二进制流 String json = "{}"; ResponseBodyEmitter speakEmitter = new ResponseBodyEmitter(); executor.execute(() -> { try { // 构造JSON部分 speakEmitter.send( MultipartBodyBuilder.part("json", json) .contentType(MediaType.APPLICATION_JSON) .build() ); // 构造二进制流部分 speakEmitter.send( MultipartBodyBuilder.part("audio", audio.readAllBytes()) .contentType(MediaType.APPLICATION_OCTET_STREAM) .build() ); // 全部内容发送完成后触发完成 speakEmitter.complete(); } catch (IOException e) { speakEmitter.completeWithError(e); } }); // 无需手动设置Content-Type头,Spring会自动生成带合法boundary的响应头 return ResponseEntity.ok(speakEmitter); }
方案说明
- 修正了原代码中
produces配置和实际响应Content-Type不匹配的问题,Spring会根据produces配置自动生成带合法boundary的响应头 - 所有多部分的边界生成、分隔符拼接、结束符追加都由Spring的
MultipartHttpMessageConverter自动处理,完全符合RFC规范 - 每个部分可以通过
MultipartBodyBuilder.PartBuilder单独设置头信息,比如Content-Disposition、自定义头字段等 - 如果使用Spring WebFlux环境,将
ResponseBodyEmitter替换为Flux<MultipartBodyBuilder.Part>即可,逻辑基本一致 - 如需自定义boundary规则,可以通过自定义配置
MultipartHttpMessageConverter实现,一般场景下使用自动生成的boundary即可满足要求
内容的提问来源于stack exchange,提问作者jimonthebarn
相关产品推荐
相关产品推荐

