Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Web Reactive Framework Multipart File Issue

I'm trying to implement and image upload using Spring's Reactive Framework by trying the following:

@RestController
@RequestMapping("/images")
public class ImageController {

    @Autowired
    private IImageService imageService;

    @PostMapping(value = "", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    Mono<ImageEntity> saveImage(@RequestBody Mono<FilePart> part) throws Exception{
         return part.flatMap(file -> imageService.saveImage(file));
    }
}

But I keep getting a 415 with the following error message:

Response status 415 with reason "Content type 'multipart/form-data;boundary=--0b227e57d1a5ca41' not supported\

Not sure what the issue is, I'm curling the API the following way:

 curl -v -F "[email protected]" -H "Content-Type: multipart/form-data" localhost:8080/images

I've tried different variations of headers and files with the same results. Kind of at a loss here because I've done this in the past and things seemed to work okay. I saw from this post that this feature was merged:

How to enable Spring Reactive Web MVC to handle Multipart-file?

like image 701
Joel Holmes Avatar asked Dec 07 '17 21:12

Joel Holmes


3 Answers

After digging around I was able to find this test in the Spring WebFlux project:

https://github.com/spring-projects/spring-framework/blob/master/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MultipartIntegrationTests.java

So the part I was missing was @RequestPart instead of @RequestBody in the controller definition.

Final code looks something like this:

@RestController
@RequestMapping("/images")
public class ImageController {

    @Autowired
    private IImageService imageService;

    @PostMapping(value = "", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    Mono<ImageEntity> saveImage(@RequestPart("file") Mono<FilePart> part) throws Exception{
         return part.flatMap(file -> imageService.saveImage(file));
    }
}
like image 116
Joel Holmes Avatar answered Nov 12 '22 15:11

Joel Holmes


Actually the following solution seems to work with Netty

    @PostMapping(path = "/test/{path}",
            consumes = MediaType.MULTIPART_FORM_DATA_VALUE, 
            produces = {MediaType.APPLICATION_JSON_VALUE})
    @ResponseBody
    Mono<String> commandMultipart(
        @PathVariable("path") String path,
        @RequestPart("jsonDto") Mono<JsonDto> jsonDto,
        @RequestPart(value = "file",required = false) Mono<FilePart> file) {
        JsonDto dto = jsonDto.block();
     }

Build.gradle

 compile group: 'org.synchronoss.cloud', name: 'nio-multipart-parser', version: '1.1.0'

 compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.3'
 compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.9.3'

curl command in bash

echo '{"test":"1"}' > command.json && curl -H "Content-Type:multipart/form-data" -X POST http://localhost:8082/test/examplepath/ -F "command=@./command.json;type=application/json" -F "[email protected]" -vv

Troubleshooting steps

  1. Ensure nio-multipart-parser is present by checking method org.springframework.http.codec.support.ServerDefaultCodecsImpl#extendTypedReaders

  2. You can check that nio-multipart-parser is used by placing breakpoint inside

    • org.springframework.http.codec.multipart.SynchronossPartHttpMessageReader#canRead() for single part
    • org.springframework.http.codec.multipart.MultipartHttpMessageReader#canRead for multipart

    One of the above methods should return true.

like image 44
Boris Treukhov Avatar answered Nov 12 '22 17:11

Boris Treukhov


In some cases the solution is to update the Spring version greater than 2.1.1, after this you should check that in the dependencies that are not 'spring-webmvc' since this generates a conflict with 'spring-boot-starter-webflux'

like image 1
andreshincapier Avatar answered Nov 12 '22 16:11

andreshincapier