如何在 Spring WebFlux 的响应主体中流式传输二进制数据
How to stream binary data in a response body in Spring WebFlux
我正在使用 Spring WebFlux 制作一个项目。
过去我曾使用 StreamingResponseBody
将响应流式传输回客户端,但我在 WebFlux 中找不到等效项。
示例:
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@GetMapping("/video")
public StreamingResponseBody stream() {
InputStream videoStream = ...
StreamingResponseBody res = (os) -> { IOUtils.copy(videoStream, os); }
return res;
}
WebFlux 是否有 StreamingResponseBody
的等价物?或者,我应该导入传统的 Spring MVC 并混合它们吗?
编辑:到目前为止,我正在通过访问 ServerHttpResponse
(下面的示例)来解决它。但我仍然想知道更好的解决方案。
@GetMapping("/video")
fun stream2(response: ServerHttpResponse): Mono<Void> {
val factory = response.bufferFactory()
val publisher = videoStream
.observeVideoParts()
.map { factory.wrap(it.bytes) }
return response.writeWith(publisher)
}
目前,我找到的最佳解决方案是 return ServerHttpResponse
。
因为ServerHttpResponse
只允许写DataBuffer
对象而不是ByteArray
对象,我做了一个扩展函数在写之前包装它们:
fun ServerHttpResponse.writeByteArrays(bytes: Flux<ByteArray>): Mono<Void> {
val factory = this.bufferFactory()
val dataBuffers = bytes.map { factory.wrap(it) }
return this.writeWith(dataBuffers)
}
那么一个Flux<ByteArray>
可以简单的写成这样:
@GetMapping("/video")
fun stream2(response: ServerHttpResponse): Mono<Void> {
val videoParts: Flux<ByteArray> = ...
return response.writeByteArrays(videoParts)
}
我仍然对其他解决方案持开放态度。
有点晚了。但是,扫描 Spring 核心和 Webflux 的最新文档,我认为以下内容应该有效:
@GetMapping("/stream/{path}")
public Flux<DataBuffer> getVideo(
@PathVariable("path") String path,
ServerHttpResponse response
) {
return DataBufferUtils.read(
new FileSystemResource(path),
response.bufferFactory(),
512
);
}
我正在使用 Spring WebFlux 制作一个项目。
过去我曾使用 StreamingResponseBody
将响应流式传输回客户端,但我在 WebFlux 中找不到等效项。
示例:
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@GetMapping("/video")
public StreamingResponseBody stream() {
InputStream videoStream = ...
StreamingResponseBody res = (os) -> { IOUtils.copy(videoStream, os); }
return res;
}
WebFlux 是否有 StreamingResponseBody
的等价物?或者,我应该导入传统的 Spring MVC 并混合它们吗?
编辑:到目前为止,我正在通过访问 ServerHttpResponse
(下面的示例)来解决它。但我仍然想知道更好的解决方案。
@GetMapping("/video")
fun stream2(response: ServerHttpResponse): Mono<Void> {
val factory = response.bufferFactory()
val publisher = videoStream
.observeVideoParts()
.map { factory.wrap(it.bytes) }
return response.writeWith(publisher)
}
目前,我找到的最佳解决方案是 return ServerHttpResponse
。
因为ServerHttpResponse
只允许写DataBuffer
对象而不是ByteArray
对象,我做了一个扩展函数在写之前包装它们:
fun ServerHttpResponse.writeByteArrays(bytes: Flux<ByteArray>): Mono<Void> {
val factory = this.bufferFactory()
val dataBuffers = bytes.map { factory.wrap(it) }
return this.writeWith(dataBuffers)
}
那么一个Flux<ByteArray>
可以简单的写成这样:
@GetMapping("/video")
fun stream2(response: ServerHttpResponse): Mono<Void> {
val videoParts: Flux<ByteArray> = ...
return response.writeByteArrays(videoParts)
}
我仍然对其他解决方案持开放态度。
有点晚了。但是,扫描 Spring 核心和 Webflux 的最新文档,我认为以下内容应该有效:
@GetMapping("/stream/{path}")
public Flux<DataBuffer> getVideo(
@PathVariable("path") String path,
ServerHttpResponse response
) {
return DataBufferUtils.read(
new FileSystemResource(path),
response.bufferFactory(),
512
);
}