On the frontend we have a form which send the data as multipart/form-data and we need to receive the data in the controller, and there could be a couple of records for the same property. We are using Spring WebFlux (spring-boot-starter-parent:2.7.3) Example
Content-Disposition: form-data; name="ids"
30
-----------------------------313589022531437741264012237550
Content-Disposition: form-data; name="ids"
225
-----------------------------313589022531437741264012237550
Content-Disposition: form-data; name="ids"
226
-----------------------------313589022531437741264012237550
Content-Disposition: form-data; name="ids"
@PostMapping(value = "/create", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Mono<String> create(@RequestPart("ids") List<Long> ids) {
// ...
}
List<Long>
and Long[]
doesn't work.
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.
Comment From: alxxyz
I've already asked this question on Stack Overflow https://stackoverflow.com/questions/73636534/receive-multiple-multipart-form-data-properties-with-the-same-name-in-spring-web
and no answer yet
Comment From: bclozel
Maybe try improving the question by adding stacktraces (if any), or providing a simple curl command or WebClient
snippet to replicate the POST content. Currently, the description doesn't make it easy to reproduce this case.
Comment From: alxxyz
@bclozel I've update the question on Stack Overflow.
The request
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
bodyBuilder.part("ids", 22);
bodyBuilder.part("ids", 33);
webTestClient.post()
.uri("/create")
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(bodyBuilder.build()))
.exchange()
.expectStatus().isOk();
The error
org.springframework.web.server.ServerWebInputException: 400 BAD_REQUEST "Failed to read HTTP message"; nested exception is org.springframework.core.codec.DecodingException: JSON decoding error: Cannot deserialize value of type `java.util.ArrayList<java.lang.Integer>` from Integer value (token `JsonToken.VALUE_NUMBER_INT`); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.ArrayList<java.lang.Integer>` from Integer value (token `JsonToken.VALUE_NUMBER_INT`)
at [Source: (org.springframework.core.io.buffer.DefaultDataBuffer$DefaultDataBufferInputStream); line: 1, column: 1]
at org.springframework.web.reactive.result.method.annotation.AbstractMessageReaderArgumentResolver.handleReadError(AbstractMessageReaderArgumentResolver.java:224)
at org.springframework.web.reactive.result.method.annotation.AbstractMessageReaderArgumentResolver.lambda$readBody$3(AbstractMessageReaderArgumentResolver.java:190)
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94)
Comment From: alxxyz
Please find the sample of the issue https://github.com/alxxyz/spring-request-part-demo
Comment From: alxxyz
@bclozel @sdeleuze So, can this ticket be converted to enhancement?
Comment From: bclozel
I think the answer on StackOverflow explains it all, the values are split across parts while @RequestPart
is meant for accessing a single part. I don't think this qualifies as an enhancement request - how should framework deserialize parts in a non-blocking fashion when all of them are required?
Assuming you can't change what the client is sending, you could use public String handle(@RequestBody Flux<Part> parts) {
as a method signature and collect
all values in a single collection.