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
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
-
Rename the out_bind_data.txt file to out_bind_data and use that file.
-
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).