REST multipart mixed request (file+json) with Spri

2020-07-03 08:22发布

I need to send a file alongside with a json to my Spring Controller. I have the following controller class:

@Controller
@RequestMapping("/perform")
public class PerformController {

    ...

    @RequestMapping(path = "gopdf", method = RequestMethod.POST, consumes = { "multipart/mixed" })
    @ResponseStatus(HttpStatus.CREATED)
    public void handleFileUpload(@RequestPart("file") MultipartFile file, @RequestPart("map") String map,   HttpServletResponse response) throws Exception {
        ...
    }

}

But when I curl on my server with the following command :

 curl -H "Content-Type: multipart/form-data" -F "map=@map.json; type=application/json" -F "content=@SMP.docx" -X POST localhost:9000/perform/gopdf-i -v

I get 415 unsupported Media Type !

Any clue ?

4条回答
Bombasti
2楼-- · 2020-07-03 08:30

The multipart/mixed for spring webflux(2.1.0) did not work for me. Here is an alternative approach that worked

  • Working - spring-boot-starter-web/Multipart[] - upload files where one is the payload, another is a file itself. In my case since the payload was constant, it worked.
  • Not working - spring-boot-starter-webflux/Flux. The flux is empty. I tried this https://github.com/spring-projects/spring-boot/issues/13268, but it didn't work
查看更多
做自己的国王
3楼-- · 2020-07-03 08:34

It's maybe related to your request mapping annotation. I think accept value is missing to determine what service can accept :

Example :

@RequestMapping(path = "gopdf", method = RequestMethod.POST, consumes = { "multipart/mixed" }, accept = MediaType.MULTIPART_FORM_DATA_VALUE)

Import :

import org.springframework.http.MediaType;

Documentation/API : http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/MediaType.html

查看更多
Evening l夕情丶
4楼-- · 2020-07-03 08:47

The consumes thing in the other answers didn't do crap for me. The key was getting the specific multipart/* types I wanted to support onto some headers key in the RequestMapping. It was really difficult to figure out, mostly guess work and stare at the Spring source code. I'm kind-of underwhelmed with Spring's support for this, but I have managed to make it work in our Spring Boot App, but only with Tomcat?!? Something called the MultipartResolver chokes when you configure your Boot application to use Jetty...so long Jetty. But I digress...

In my Controller I set up for multipart/mixed or multipart/form-data like...

@RequestMapping(value = "/user/{userId}/scouting_activities", method = RequestMethod.POST,
        headers = {"content-type=multipart/mixed","content-type=multipart/form-data"})
public ResponseEntity<String> POST_v1_scouting_activities(
        @RequestHeader HttpHeaders headers,
        @PathVariable String userId,
        @RequestPart(value = "image", required = false) MultipartFile image,
        @RequestPart(value = "scouting_activity", required = true) String scouting_activity_json) {
  LOG.info("POST_v1_scouting_activities: headers.getContentType(): {}", headers.getContentType());
  LOG.info("POST_v1_scouting_activities: userId: {}", userId);
  LOG.info("POST_v1_scouting_activities: image.originalFilename: {}, image: {}",
          (image!=null) ? image.getOriginalFilename() : null, image);
  LOG.info("POST_v1_scouting_activities: scouting_activity_json.getType().getName(): {}, scouting_activity: {}",
          scouting_activity_json.getClass().getName(), scouting_activity_json);
  return new ResponseEntity<String>("POST_v1_scouting_activities\n", HttpStatus.OK);
}

That headers thing let it uniquely identify the multipart content types it was willing to take a shot at. This lets curls like...

curl -i -X POST 'http://localhost:8080/robert/v1/140218/scouting_activities' \
-H 'Content-type:multipart/mixed' \
-F 'image=@Smile_128x128.png;type=image/png' \
-F 'scouting_activity={
  "field": 14006513,
  "longitude": -93.2038253,
  "latitude": 38.5203231,
  "note": "This is the center of Dino Head.",
  "scouting_date": "2017-01-19T22:56:04.836Z"
};type=application/json'

...or...

curl -i -X POST 'http://localhost:8080/robert/v1/140218/scouting_activities' \
-H 'Content-type:multipart/form-data' \
-F 'image=@Smile_128x128.png;type=image/png' \
-F 'scouting_activity=@scoutingFrackingCurl.json;type=application/json'

work.

查看更多
神经病院院长
5楼-- · 2020-07-03 08:49

I've found the solution: I need to use @RequestParam instead of @RequestPart

@RequestMapping(path = "gopdf", method = RequestMethod.POST, consumes = { "multipart/form-data" })
@ResponseStatus(HttpStatus.OK)
public void handleFileUpload2(@RequestParam("file") MultipartFile file, @RequestParam("map") String jsonMap,
        HttpServletResponse response) throws Exceptio
查看更多
登录 后发表回答