it-roy-ru.com

REST многокомпонентный смешанный запрос (файл + json) с Spring

Мне нужно отправить файл вместе с 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 {
        ...
    }

}

Но когда я свернулся на моем сервере с помощью следующей команды:

 curl -H "Content-Type: multipart/form-data" -F "[email protected]; type=application/json" -F "[email protected]" -X POST localhost:9000/perform/gopdf-i -v

Я получаю 415 неподдерживаемых типов носителей!

Любая подсказка?

6
ElArbi

То, что потребляет в других ответах, не для меня. Ключ получал определенные типы multipart/*, которые я хотел поддерживать, на ключ некоторых заголовков в RequestMapping. Это было действительно трудно понять, в основном угадывать работу и смотреть на исходный код Spring. Я немного разочарован поддержкой Spring для этого, но мне удалось заставить его работать в нашем приложении Spring Boot, но только с Tomcat?!? Что-то, называемое дросселями MultipartResolver, когда вы конфигурируете свое загрузочное приложение для использования Jetty ... так долго 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);
}

Эта штука заголовков позволяет однозначно идентифицировать составные типы контента, на которые он был готов. Это позволяет завитки как ...

curl -i -X POST 'http://localhost:8080/robert/v1/140218/scouting_activities' \
-H 'Content-type:multipart/mixed' \
-F '[email protected]_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'

...или же...

curl -i -X POST 'http://localhost:8080/robert/v1/140218/scouting_activities' \
-H 'Content-type:multipart/form-data' \
-F '[email protected]_128x128.png;type=image/png' \
-F '[email protected];type=application/json'

работа.

4
Bob Kuhar

Я нашел решение: Мне нужно использовать @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
2
ElArbi

Multipart/mixed для весеннего webflux (2.1.0) у меня не сработало. Вот альтернативный подход, который работал

  • Рабочая - spring-boot-starter-web/Multipart [] - загрузка файлов, где one - полезная нагрузка, другой - сам файл. В моем случае, поскольку полезная нагрузка была постоянной, это работало.
  • Не работает - spring-boot-starter-webflux/Flux. Флюс пуст. Я попробовал это https://github.com/spring-projects/spring-boot/issues/13268 , но это не сработало
1
Aravind

Возможно, это связано с аннотацией сопоставления вашего запроса. Я думаю, что значение accept отсутствует, чтобы определить, какую службу можно принять:

Пример :

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

Импортировать :

import org.springframework.http.MediaType;

Документация/API:http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/MediaType.html

0
Mickael