Content type 'multipart/form-data;boundary=----...;charset=UTF-8' not supported
Asked Answered
P

9

53

I want to send an object to the controller that has several lists with files and several fields with plain text.

public class ContributionNew<T extends MovieInfoDTO> {
    private List<T> elementsToAdd;
    private Map<Long, T> elementsToUpdate;
    private Set<Long> idsToDelete;
    private Set<String> sources;
    private String comment;
}

public class Photo extends MovieInfoDTO {
    private MultipartFile photo;
}

@PostMapping(value = "/{id}/contributions/photos")
@ResponseStatus(HttpStatus.CREATED)
public
ResponseEntity<Void> createPhotoContribution(
        @ApiParam(value = "The movie ID", required = true)
        @PathVariable("id") final Long id,
        @ApiParam(value = "The contribution", required = true)
        @RequestBody @Valid final ContributionNew<Photo> contribution
) {

I am sending data using postman. However, he throws me away

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundarywY7ByvgonAjDoaCT;charset=UTF-8' not supported

What should I set the Content-type for this controller so that I can send an object that has fields of plain text and lists with files?

If I set the header in the header

Content-type: multipart/form-data; charset=utf-8

it throws me in the console

org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
Protohuman answered 1/1, 2018 at 16:7 Comment(3)
Don't know if it matters, but multipart/form-data should not have a charset. It does need a boundary though. See WWW Specification.Grindle
More likely, though, it is the ---- in the boundary that cause trouble, since -- has special meaning for boundary markers.Grindle
@RequestBody means to parse JSON data into map or java beans and only support content type is "application/json;charset=UTF-8"Riedel
G
65

As said dknight @RequestBody means use of JSON or XML data with maps your DTO bean. In case of MultipartFile you can't use JSON data so you can't use @RequestBody. Try with @ModelAttribute annotation.

Working sample :

@PostMapping("/promoters")
@Timed
public ResponseEntity<PromoterDTO> createPromoter(@ModelAttribute PromoterDTO promoterDTO) throws URISyntaxException { ... }

With PromoterDTO like this :

    public class PromoterDTO implements Serializable {

        private Long id; 

        private String name;

        private String address;

        private MultipartFile logo;
    }
Gladis answered 23/8, 2018 at 9:13 Comment(5)
I'm getting null values in my object after implementing this. All the fields are nullRabies
Have you set the getters and setters ?Gladis
If I use @ModelAttribute in my case, I get that it can't convert from string to my child DTO (my main DTO has other DTO in it). How can I fix that?Ego
Doing exactly as this states the DTO is populated correctly but the variable "logo" ist still null. Any ideas?Alectryomancy
Also in my case the file field is null after. With ModelAttribute the object is saved in database (with RequestBody i was not able to do it) but the file field is null. Any ideas?Incursion
C
35

In Postman, you need to set the body to be of type raw, and from the drop down you can select JSON, I had a similar issue, this fixed my issue.

view screen here

Canning answered 9/4, 2018 at 15:42 Comment(1)
How does this allow the upload of files as well?Swanson
S
8

Instead of @RequestBody, use @RequestParam!

Sweepings answered 24/7, 2019 at 6:44 Comment(2)
Could you explain in more detail how this will fix the OP's problem?Serous
to send files content-type should be multipart/form-data so requestparam takes in formdata but for request body content-type should be application/json that not handle files.Sweepings
B
8

Hi Folks simply change : @RequestBody to @ModelAttribute

public ResponseEntity<DTO> exemple(@ModelAttribute Dto dto) throws TechnicalException

Happy coding.

Bastard answered 20/9, 2022 at 9:2 Comment(0)
F
5
import org.springframework.web.bind.annotation.ModelAttribute;

Use @ModelAttribute instead of @RequestBody. It worked for me.

Funnelform answered 5/3, 2021 at 11:43 Comment(1)
Hi my friend, That works for me...Ataghan
G
4

use @ModelAttribute instead of @ResponseBody as this takes up data in key value pairs and the later is used for an object like, json. While hitting the api simply pass the multipart type and json key value pairs of the object. It works fine!

stack overflow question on this

Gadmann answered 26/1, 2020 at 6:6 Comment(0)
E
3

Instead of @RequestBody, use @ModelAttribute like,

@PostMapping(value = "/{id}/contributions/photos")
@ResponseStatus(HttpStatus.CREATED)
public
ResponseEntity<Void> createPhotoContribution(
        @ApiParam(value = "The movie ID", required = true)
        @PathVariable("id") final Long id,
        @ApiParam(value = "The contribution", required = true)
        @ModelAttribute @Valid final ContributionNew<Photo> contribution
) {
Endodontist answered 27/6, 2019 at 10:59 Comment(0)
F
2

produces = { "application/json" } has to written in the controller instead of consumes = { "application/json" }

Frontlet answered 27/5, 2021 at 7:54 Comment(0)
S
1

Here's a full code sample written in Kotlin using Spring Boot 2.1.7

Example uses a ProfileRepository that would be something you implement of course.

Kotlin is nice, because the data class implements serializable already.

Take note, that you have to use var not val for the model objects properties otherwise the field values will be null in the log message.

import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.multipart.MultipartFile

@RestController
class ExampleController(private val myProfileRepository: ProfileRepository) {
    
    @PostMapping("/api/uploadFile")
    fun createProvider(@ModelAttribute request: CreateProfileRequest): Provider {
        println("received create request with photo: ${request.photo} for the following person ${request.name}")
        return myProfileRepository.save(Provider(name = request.name!!))
    }
}

data class CreateProfileRequest(
    var name: String? = null,
    var photo: MultipartFile? = null
)
Silvasilvain answered 24/5, 2021 at 9:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.