Receive multiple multipart/form-data properties with the same name in Spring WebFlux

Viewed 55

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

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"

How to receive these values in the controller?

@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.

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)

Here's a repo to demonstrate the problem:

https://github.com/alxxyz/spring-request-part-demo

1 Answers

If you form your IDs as an array, they will be handled corrected:

        MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
        bodyBuilder.part("ids", Arrays.asList(22, 33));
        //bodyBuilder.part("ids", 33);

        webTestClient.post()
                .uri("/create")
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .body(BodyInserters.fromMultipartData(bodyBuilder.build()))
                .exchange()
                .expectStatus().isOk();
Related