The following controller method causes a HttpMediaTypeNotSupportedException. If I change the tenantId parameter to a String everything works fine.

@RequestMapping(value = "/test", method = RequestMethod.POST, consumes = {"multipart/form-data"})
    public ResponseEntity<TemplateResponse> templatesPost(@RequestPart(value = "tenantId", required = true) Long tenantId,
                                                          @RequestPart(value = "file", required = true) MultipartFile file,
                                                          @RequestPart(value = "subject", required = true) String subject,
                                                          @RequestPart(value = "type", required = true) String type) throws IOException {
        Template template = new Template(tenantId, subject, type, file.getBytes());
        TemplateResponse response = templateService.save(template);
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

This is the error response from Spring:

{
  "timestamp": "2017-03-01T05:05:05.026Z",
  "status": 415,
  "error": "Unsupported Media Type",
  "exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
  "message": "Content type 'application/octet-stream' not supported",
  "path": "/notification/test"
}

I've tried wrapping the other params in an object, and I get the same response.

Comment From: wilkinsona

I would guess that there's no converter to turn the tenantId request part into a long. I can't tell for sure without some more context.

If you would like us to spend some time trying to help you, please spend some time providing a complete sample that reproduces the problem. A git repository that contains a small app and a test that reproduces the failure would be ideal.

Comment From: browndogg33

Andy, I'll take a look at that today but I'm in a course most of the day so I'll be able to reply back either tonight or tomorrow. Thank you for the quick response.

Sent from my iPhone

On Mar 1, 2017, at 1:08 AM, Andy Wilkinson notifications@github.com wrote:

I would guess that there's no converter to turn the tenantId request part into a long. I can't tell for sure without some more context.

If you would like us to spend some time trying to help you, please spend some time providing a complete sample that reproduces the problem. A git repository that contains a small app and a test that reproduces the failure would be ideal.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

Comment From: browndogg33

Are you saying explicitly register a type converter? Here's a repo with a simple example https://github.com/browndogg33/multipart.git. I'm sure its something simple.

Comment From: philwebb

@browndogg33 The test fails because it's not simulating a file upload and not setting the content type. You might want to look at this stack overflow post.

Can you provide a sample that works with the String but fails with the Long? Also can you check how you're hitting the endpoint. Perhaps your content type header isn't multipart/form-data?

Comment From: browndogg33

Ok, I updated the tests here. They are not working for a different reason now. It can't find the id param. However, if I change the method signature to use @RequestParam instead of @RequestPart they work. As part of the actual project, though, I am using Swagger to generate the server stubs, so I can't just update those signatures manually to use @RequestParam.

If I use Postman to test, I still see the original behavior. It works with String id, but not Long id.

long_postman

string_postman

Comment From: philwebb

Change the ID @RequestPart to a @RequestParam

@RequestParam(value = "id", required = true) String id

This section of the JavaDoc explains more:

Note that @RequestParam annotation can also be used to associate the part of a "multipart/form-data" request with a method argument supporting the same method argument types. The main difference is that when the method argument is not a String, @RequestParam relies on type conversion via a registered Converter or PropertyEditor while @RequestPart relies on HttpMessageConverters taking into consideration the 'Content-Type' header of the request part. @RequestParam is likely to be used with name-value form fields while @RequestPart is likely to be used with parts containing more complex content (e.g. JSON, XML)

Comment From: palossyl

multipart/form-data with @RequestPart relies on HttpMessageConverters.

Without registering such a converter, you can use only String and MultipartFile parameters, when consuming multipart/form-data.

As quick fix change Long tenantId to String tenantId, and parse it into a Long value!

Comment From: Maxvgrad

Please, check the answer. I hope it would be helpful! https://stackoverflow.com/a/55195925/9215813

Comment From: SympathyForTheDev

unfortunately in 2019 I ran in the same issue, I'm using spring boot 1.5.x and java 8.

this doesn't work out of the box (I get the error "Content type 'application/octet-stream' not supported'")

@PostMapping(value = "/upload_with_metadata", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResponseDTO uploadWithMetadata(@RequestPart final Long id, @RequestPart(value = "attachment", required = false) final MultipartFile attachment) {
      return service.doStuff(id, attachment)
    }

it's work with the work around :

@PostMapping(value = "/upload_with_metadata", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResponseDTO uploadWithMetadata(@RequestPart final String id, @RequestPart(value = "attachment", required = false) final MultipartFile attachment) {
      return service.doStuff(Long.valueOf(id), attachment)
    }

Comment From: wilkinsona

@DevWantJustHaveFun As suggested above, you should use @RequestParam rather than @RequestPart for the id parameter.

Comment From: SympathyForTheDev

@wilkinsona

unfortunately this doesn't work: @RequestParam final String id, @RequestPart(value = "attachment", required = false) final MultipartFile attachment)

I'm getting this error :

org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'id' is not present

but this work : @RequestPart final String id, @RequestPart(value = "attachment", required = false) final MultipartFile attachment)

with the same payload :

-----------------------------70814921010884712821200113244 Content-Disposition: form-data; name="id"

13491

-----------------------------70814921010884712821200113244 Content-Disposition: form-data; name="attachment"; filename="test.txt" Content-Type: application/octet-stream

hello test -----------------------------70814921010884712821200113244--

but my original point is thinking about "@RequestPart final Long id" was working out of the box

Comment From: wilkinsona

I believe it should work. Unfortunately, I can't tell why without some more context. The functionality in question is part of Spring MVC in Spring Framework rather than being part of Spring Boot so this isn't really the right place to diagnose the problem.

my original point is thinking about "@RequestPart final Long id" was working out of the box

This won't work for the reasons explained in Phil's comment that I linked to earlier. @RequestPart uses HTTP message conversion taking into account the Content-Type header of the part. There is no standard HTTP message converter that will be able to turn the String input into a Long. If your id parameter is a String, no type conversion is necessary. Alternatively, @RequestParam uses a Converter or PropertyEditor. This will be able to perform the String to Long conversion by default so you should be able to make your id parameter a Long if you annotate it with @RequestParam.

If you have any further questions, please follow up on Stack Overflow or Gitter. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.

Comment From: ashok2ashok

The RequestParam value cannot be the same as the parameter field name in the method. But the RequestParam value should match the requested name

These didn't work.

@RequestParam(value = "files") MultipartFile[] files
@RequestPart(value = "files") MultipartFile[] files

But the below options worked.

@RequestParam(value = "files") MultipartFile[] uploadedFiles
@RequestPart(value = "files") MultipartFile[] uploadedFiles

Comment From: Jiajun-Huang

Change to @RequestParam worked but also allowed the request likehttp://localhost:8080/blog/upload?published=true&commentable=true' to work which I don't think is a behavior you want.