How to upload mono of json and flux of files with webflux

…衆ロ難τιáo~ 提交于 2020-01-16 08:38:10

问题


I'm looking for a piece of code with Webflux that can handle a json part and a files stream. The request can upload a lot of files so I want to process one file at the time with zero copy by using a Flux (and not a flux on a preloaded Map). I think I tried everything and this is my last implementation that doesn't work well:

This is my unit test:

@Test
@DisplayName("[TU] Http upload series")
public void uploadSeries() {

    ArgumentCaptor<Mono<SeriesMetaDTO>> metaMono = ArgumentCaptor.forClass(Mono.class);
    ArgumentCaptor<Flux<DataBuffer>> dicomFlux = ArgumentCaptor.forClass(Flux.class);

    doReturn(Flux.empty()).when(service).create(any(), any());

    webTestClient.post()
            .uri(SeriesApiRouter.RESOURCE)
            .bodyValue(generateBody())
            .exchange()
            .expectStatus().is2xxSuccessful()
    ;

    verify(service).create(metaMono.capture(), dicomFlux.capture());

    StepVerifier.create(metaMono.getValue().log())
            .expectNext(new SeriesMetaDTO(List.of("TITI", "TOTO")))
            .verifyComplete();

    StepVerifier.create(dicomFlux.getValue().log())
            .expectNextCount(3)
            .verifyComplete();
 }

A controller way approch:

@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Mono<ServerResponse> postStreamSeries(
        @RequestPart("meta") Mono<SeriesMetaDTO> meta,
        @RequestPart("dicoms") Flux<Part> dicoms
) {
    var dicomsFlux = dicoms
            .map(Part::content)
            .flatMap(DataBufferUtils::join)
            .log()
            ;
    return ServerResponse.ok().body(BodyInserters.fromPublisher(service.create(meta, dicomsFlux), String.class));
}

A functional way approch:

 public Mono<SeriesMetaDTO> extractSerieMeta(MultiValueMap map) {
    return (Mono<SeriesMetaDTO>) map.getFirst("meta");
}

public Mono<ServerResponse> postStreamSeries(ServerRequest request) {

    var meta = request.multipartData()
            .flatMap(this::extractSerieMeta)
            .ofType(SeriesMetaDTO.class)
            .single();

    var files = request.body(BodyExtractors.toParts())
            .ofType(FilePart.class)
            .map(Part::content)
            .flatMap(DataBufferUtils::join);

    return ServerResponse.ok().body(BodyInserters.fromPublisher(service.create(meta,files), String.class));
}

Can you see what I missed here? Thanks you.

来源:https://stackoverflow.com/questions/58500409/how-to-upload-mono-of-json-and-flux-of-files-with-webflux

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!