如何在Spring WebFlux中的响应主体中传输二进制数据

时间:2017-12-23 17:05:40

标签: java spring spring-mvc kotlin 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)
}

2 个答案:

答案 0 :(得分:0)

目前,我找到的最佳解决方案是返回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)
}

我仍然愿意接受其他解决方案。

答案 1 :(得分:-1)

有点晚了。但是,扫描Spring核心和Webflux的最新文档,我认为以下方法应该有效:

@GetMapping("/stream/{path}")
public Flux<DataBuffer> getVideo(
        @PathVariable("path") String path,
        ServerHttpResponse response
) {
    return DataBufferUtils.read(
            new FileSystemResource(path),
            response.bufferFactory(),
            512
    );
}