I am using Webflux and Netty in my spring boot application. I am sending the multipart data as a request to my controller class. Flux is the request body from ServerHttpRequest in my controller class. We are trying to get the data as byte[] format from Flux and then constructing the data as string format. The issue we are facing is the data is truncated.

Please find the code snippet

public class ReactiveController {

@RequestMapping(value = "/test4", method = RequestMethod.PUT)
    @RequestScope
    public CompletableFuture<ResponseEntity<?>> test4(ServerHttpRequest req, RequestEntity<String> reqEntity)
            throws Exception {

        Flux<DataBuffer> fluxData = req.getBody();
        System.out.println("Flux string:" + fluxToString(fluxData));
        final CompletableFuture<ResponseEntity<?>> finalRspCompFuture = new CompletableFuture<>();
        ResponseEntity<?> rspEntity = new ResponseEntity<>(HttpStatus.OK);
        finalRspCompFuture.complete(rspEntity);
        return finalRspCompFuture;
    }

    public String fluxToString(Flux<DataBuffer> fluxRequestBody) {
        StringBuilder sb = new StringBuilder();
        fluxRequestBody.subscribe(buffer -> {
            byte[] bytes = new byte[buffer.readableByteCount()];
            buffer.read(bytes);
            DataBufferUtils.release(buffer);
            String bodyString = new String(bytes, StandardCharsets.UTF_8);
            sb.append(bodyString);
        });
        return sb.toString();
    }
}

Expected behavior

Content-Disposition: form-data; name="metadata"; filename="new.txt"
Content-Type: application/json

test1
--------------------------1a1017604f70f540
Content-Disposition: form-data; name="content"; filename="out_bind_data"
Content-Type: application/vnd.3gpp.5gnas
.Á¡{'!

Actual behavior

Content-Disposition: form-data; name="metadata"; filena (truncated)...

Steps to reproduce

  1. Rename the out_bind_data.txt file to out_bind_data and use that file.

  2. Please send the request using curl command which is given below

curl -X PUT -v http://localhost:8080/test4 -H "content-type: multipart/mixed" -F "metadata=@new.txt; type=application/json" -F "content=@out_bind_data; type=application/vnd.3gpp.5gnas"

Environment

SpringBootVersion: 2.4.3 java : 16 new.txt out_bind_data.txt

Comment From: bclozel

Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use the issue tracker only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add some more details if you feel this is a genuine bug.

In this case, your code is trying to manually build a CompletableFuture and completely ignores the concurrency aspect of it. You should never call subscribe in a controller method and instead this should return a Mono or a Flux type. Calling subscribe here starts consuming the request body asynchronously in a worker thread. The line right under it returns right away the string when we're not done reading the request. This explains the truncated body.

Comment From: techdeba901

Thanks for your response. Please tell me how can I read multipart data using ServerHttpRequest.

Comment From: bclozel

You can get the ServerWebExchange as a method argument instead and get the multipart data from it (see also this).