如何< DataBuffer>在Spring控制器中将Flux转换为StreamingResponseBody

hwazgwia  于 2023-11-16  发布在  Spring
关注(0)|答案(1)|浏览(312)

我在Spring Controller中有一个Flux of DataBuffer,我想将它作为流附加到StreamingResponseBody。我已经阅读了许多类似方法的答案,但没有一个与此完全匹配。我不想将整个文件加载到内存中。我希望它流。

@GetMapping(value="/attachment")
public ResponseEntity<StreamingResponseBody> get(@PathVariable long attachmentId) {

    Flux<DataBuffer> dataBuffer = this.myService.getFile(attachmentId);

    StreamingResponseBody stream = out -> {
       // what do do here?
    }

    return ResponseEntity.ok()
        .contentType(MediaType.APPLICATION_OCTET_STREAM)
        .body(stream);
    }
}

字符串

编辑:myService.getFile()

public Flux<DataBuffer> gteFile(long attachmentId) {

    return this.webClient.get()
        .uri("https://{host}/attachments/{attachmentId}", host, attachmentId)
        .attributes(clientRegistrationId("attachmentClient"))
        .accept(MediaType.ALL)
        .exchangeToFlux(clientResponse -> clientResponse.bodyToFlux(DataBuffer.class));
}

wvt8vs2t

wvt8vs2t1#

如果你使用WebFlux,不需要返回StreamingResponseBody,你可以直接返回Flux<DataBuffer>,这样它就可以流传输,也可以不阻塞。
如果你想添加一些标题/自定义你的响应,你可以返回Mono<ResponseEntity<Flux<DataBuffer>>>

@GetMapping("/attachment/{attachmentId}")
public Mono<ResponseEntity<Flux<DataBuffer>>> get(@PathVariable long attachmentId) {

    Flux<DataBuffer> dataBuffers = this.myService.getFile(attachmentId);
    
    ContentDisposition contentDisposition = ContentDisposition.inline()
            .filename("example.txt")
            .build();

    HttpHeaders headers = new HttpHeaders();
    headers.setContentDisposition(contentDisposition);

    return Mono.just(ResponseEntity.ok()
            .headers(headers)
            .contentType(MediaType.APPLICATION_OCTET_STREAM)
            .body(dataBuffers));
}

字符串
如果你想使用StreamingResponseBody(这意味着你在web层上使用阻塞的Spring MVC),那么你可以这样做:

StreamingResponseBody stream = outputStream ->
        Mono.create(sink -> DataBufferUtils.write(dataBuffers, outputStream)
                .subscribe(DataBufferUtils::release, sink::error, sink::success)
        ).block();


然后从控制器返回

相关问题