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?
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));
}
}
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
Ensure nio-multipart-parser is present by checking method
org.springframework.http.codec.support.ServerDefaultCodecsImpl#extendTypedReaders
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 multipartOne of the above methods should return true.
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'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With