4

I am using spring-webflux and want to upload files .... everything works great with just spring-web but when it comes to webflux i have not a clue what's wrong .

Be careful in the difference ... i am using :

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

So let's say we have the below @RestController , for Spring Web it works like charm:

@PostMapping(value = "/uploadFile")
public Response uploadFile(@RequestParam("file") MultipartFile file) {

}

Now trying the same with Spring-webflux produces the below error :

{
    "timestamp": "2019-04-11T13:31:01.705+0000",
    "path": "/upload",
    "status": 400,
    "error": "Bad Request",
    "message": "Required MultipartFile parameter 'file' is not present"
}

I found from a random stackoverflow question that i have to use @RequestPart instead of @RequestParam but now i am getting the below error and i don't have a clue why this happens ?

The error is the below :

{
    "timestamp": "2019-04-11T12:27:59.687+0000",
    "path": "/uploadFile",
    "status": 415,
    "error": "Unsupported Media Type",
    "message": "Content type 'application/xml' not supported for bodyType=org.springframework.web.multipart.MultipartFile"
}

Even with .txt files is producing the same error :

{
    "timestamp": "2019-04-11T12:27:59.687+0000",
    "path": "/uploadFile",
    "status": 415,
    "error": "Unsupported Media Type",
    "message": "Content type 'application/xml' not supported for bodyType=org.springframework.web.multipart.MultipartFile"
}

Below is the Postman Configuration which is pretty straight forward , i am just calling with a post request and modified only the body as shown in the picture .

enter image description here

By the way i have added the needed properties on application.properties too :)

## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=200MB
# Max Request Size
spring.servlet.multipart.max-request-size=215MB
GOXR3PLUS
  • 5,939
  • 3
  • 30
  • 79
  • Possible duplicate of [What is http multipart request?](https://stackoverflow.com/questions/16958448/what-is-http-multipart-request) – JEY Apr 11 '19 at 12:39
  • Well if you look a at the answer you will see that the content-type for a multipart can't be application/xml. So there is that. – JEY Apr 11 '19 at 12:47
  • @JEY I get the same error for text/plain or whatever file i add sir :) – GOXR3PLUS Apr 11 '19 at 12:48
  • I think there is a problem with your request cause I created a sample project https://gist.github.com/Julien-Eyraud/4a9384e11372004d0218a9e8a961108a and it just work – JEY Apr 11 '19 at 13:05
  • @JEY I followed this tutorial :) https://www.callicoder.com/spring-boot-file-upload-download-rest-api-example/ but he is using `spring-web` we are using `spring-webflux` and there is all the problem . I used the same request for `spring-web` and it works :'( i am troubleshouting with it all day :( – GOXR3PLUS Apr 11 '19 at 13:06
  • @JEY can you show me how you called it from postman or something :) ? I will be very happy to accept your answer . – GOXR3PLUS Apr 11 '19 at 13:10
  • @JEY using your service with a `.txt` file i get the below : `Content type 'text/plain' not supported for bodyType=org.springframework.web.multipart.MultipartFile` – GOXR3PLUS Apr 11 '19 at 13:12
  • https://ibb.co/q9KppgY don't know if it's helping. But I can see that you set a header. I didn't – JEY Apr 11 '19 at 13:22
  • Completely modified the question with new image so you can see what exactly happens . Please see that i am using `spring-webflux` – GOXR3PLUS Apr 11 '19 at 13:37
  • @JEY Somebody posted an amazing answer .... as you can see it was complicated :) – GOXR3PLUS Apr 11 '19 at 14:00

1 Answers1

4

As documentation sais :

The DefaultServerWebExchange uses the configured HttpMessageReader<MultiValueMap<String, Part>> to parse multipart/form-data content into a MultiValueMap.

To parse multipart data in streaming fashion, you can use the Flux returned from an HttpMessageReader instead.

With few words you need to do something like this:

    @RequestMapping(path = "/uploadFile", method = RequestMethod.POST, 
        consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Flux<String> uploadFile(@RequestBody Flux<Part> parts) {
    //...
    }

Look at this example

Community
  • 1
  • 1
Nikolay Hristov
  • 1,431
  • 1
  • 14
  • 20
  • Thank you Nikolay , i am very new to this ... how i can get the file from inside the parts :) ? – GOXR3PLUS Apr 11 '19 at 13:39
  • 2
    Look at [this example](https://github.com/entzik/reactive-spring-boot-examples/blob/master/src/main/java/com/thekirschners/springbootsamples/reactiveupload/ReactiveUploadResource.java) – Nikolay Hristov Apr 11 '19 at 13:41
  • You already learned that switching from web to webflux is more than changeing the artifactId ;) – Nikolay Hristov Apr 11 '19 at 13:47
  • Nikolay i have a question ? Will this work okay for 1 GB files or the Service will crash ? – GOXR3PLUS Apr 11 '19 at 14:52
  • 1
    Webflux works great for uploading/downloading large files. There were [some issues](https://github.com/spring-projects/spring-framework/issues/21879) for streaming very large files few months ago but I think it is fixed now. It all depends on how is used. – Nikolay Hristov Apr 11 '19 at 18:00