Home > Enterprise >  how to read Flux<DataBuffer> content in Reactor
how to read Flux<DataBuffer> content in Reactor

Time:01-31

i want to read mulitpart/formdata,one part is application/json。i can`t get them to Map<String,String>, Is there any way to parse Part to String?

private Map<String, String> getFormData(String path,
                                            MultiValueMap<String, Part> partMultiValueMap) {
        if (partMultiValueMap != null) {
            Map<String, String> formData = new HashMap<>();
            Map<String, Part> multiPartMap = partMultiValueMap.toSingleValueMap();
            for (Map.Entry<String, Part> partEntry : multiPartMap.entrySet()) {
                Part part = partEntry.getValue();
                if (part instanceof FormFieldPart) {
                    formData.put(partEntry.getKey(), ((FormFieldPart) part).value());
                } else {
                    String bodyString = bufferToStr(part.content());
                    formData.put(partEntry.getKey(), bodyString);

                }
            }
            return formData;
        }
        return null;
    }

extra Flux

private String bufferToStr(Flux<DataBuffer> content){
        AtomicReference<String> res = new AtomicReference<>();
        content.subscribe(buffer -> {
            byte[] bytes = new byte[buffer.readableByteCount()];
            buffer.read(bytes);
            DataBufferUtils.release(buffer);
            res.set(new String(bytes, StandardCharsets.UTF_8));
        });
        return res.get();
    }

subscribe is asyncbufferToStrvalue may be null?

CodePudding user response:

You could do it in non-blocking way with StringDecoder

Basically you could write your code to return Mono<Map<>>

Note: I'm using Pair class here to return key-value and later collect them to Map

Pair I'm using here is from package org.springframework.data.util.Pair

public Mono<Map<String, String>> getFormData(MultiValueMap<String, Part> partMultiValueMap) {
    Map<String, Part> multiPartMap = partMultiValueMap.toSingleValueMap();

    return Flux.fromIterable(multiPartMap.entrySet())
            .flatMap(entry -> {
                Part part = entry.getValue();
                if (part instanceof FormFieldPart) {
                    return Mono.just(
                            Pair.of(entry.getKey(), ((FormFieldPart) part).value()) // return Pair
                    );
                } else {
                    return decodePartToString(part.content()) // decoding DataBuffers to string
                            .flatMap(decodedString ->
                                    Mono.just(Pair.of(entry.getKey(), decodedString))); // return Pair
                }
            })
            .collectMap(Pair::getFirst, Pair::getSecond); // map and collect pairs to Map<>
}

private Mono<String> decodePartToString(Flux<DataBuffer> dataBufferFlux) {
    StringDecoder stringDecoder = StringDecoder.textPlainOnly();

    return stringDecoder.decodeToMono(dataBufferFlux,
            ResolvableType.NONE,
            MimeTypeUtils.TEXT_PLAIN,
            Collections.emptyMap()
    );
}
  • Related