使用Spring的REST多部分混合请求(文件+ json)

ElA*_*rbi 10 rest spring curl spring-mvc spring-boot

我需要将一个文件与json一起发送到我的Spring Controller.我有以下控制器类:

@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 {
        ...
    }

}
Run Code Online (Sandbox Code Playgroud)

但是当我使用以下命令在我的服务器上卷曲时:

 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
Run Code Online (Sandbox Code Playgroud)

我得到415不支持的媒体类型!

任何线索?

ElA*_*rbi 5

我找到了解决方案:我需要使用 @RequestParam 而不是 @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
Run Code Online (Sandbox Code Playgroud)

  • 这不再是 multipart/mixed,它是 multipart/form-data。 (6认同)

Bob*_*har 5

其他答案中的消耗内容对我来说没有废话。关键是将我想要支持的特定 multipart/* 类型添加到 RequestMapping 中的某些标头键上。真的很难弄清楚,主要是猜测工作并盯着Spring源代码。我对 Spring 对此的支持有点不知所措,但我已经设法让它在我们的 Spring Boot 应用程序中工作,但只能与 Tomcat 一起使用?!?当您将启动应用程序配置为使用 Jetty 时,称为 MultipartResolver 的东西会窒息……那么长 Jetty。但我离题了...

在我的控制器中,我设置了 multipart/mixed 或 multipart/form-data 像...

@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);
}
Run Code Online (Sandbox Code Playgroud)

那个标题让它唯一地标识它愿意尝试的多部分内容类型。这让卷发像...

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'
Run Code Online (Sandbox Code Playgroud)

...或者...

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'
Run Code Online (Sandbox Code Playgroud)

工作。


Mic*_*ael 0

这可能与您的请求映射注释有关。我认为accept缺少确定什么服务可以接受的价值:

例子 :

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

进口 :

import org.springframework.http.MediaType;
Run Code Online (Sandbox Code Playgroud)

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