Spring Контроллер @RequestBody с возможностью загрузки файлов возможен?
У меня есть такой контроллер, и я хочу отправить форму с загрузкой файла, а также некоторые данные формы, такие как метка, как показано ниже. Кроме того, я хочу сделать это с помощью @RequestBody, чтобы я мог использовать аннотацию @Valid для оболочки, так как будет добавлено больше переменных.
public @ResponseBody WebResponse<Boolean> updateEUSettings(
final Locale locale,
@Validated @ModelAttribute final EUPSettingsWrapper endUserPortalSettingsWrapper) {
}
И моя обертка это:
public class EUPSettingsWrapper {
private String label;
private MultipartFile logo;
// getter , setters..etc...
}
Но я хотел бы преобразовать его в @RequestBody из ModelAttributes.
Я пытаюсь разделить загрузку файла как параметр запроса, например так:
public @ResponseBody WebResponse<Boolean> updateEUSettings(
final Locale locale,
@Validated @RequestBody final EUPSettingsWrapper endUserPortalSettingsWrapper,
@RequestParam(value = "file1", required = true) final MultipartFile logo) {
endUserPortalSettingsWrapper.setLogo(logo);
// ...
}
В моем макете MVC я устанавливаю:
getMockMvc().perform(fileUpload(uri).file(logo)
.accept(MediaType.APPLICATION_JSON)
.content(JSONUtils.toJSON(wrapper))
.contentType(MediaType.MULTIPART_FORM_DATA))
.andExpect(status().isOk());
Но я получаю такую ошибку, которая говорит:
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data' not supported
У кого-нибудь есть хорошее представление о том, как многокомпонентные загрузки файлов можно использовать с @RequestBody? Что-то я не так делаю выше?
Ответы
Ответ 1
Вы можете действительно упростить свою жизнь здесь, так как все, что вы делаете, это отправляете форму, которая содержит некоторые поля и файл. Вам не нужен @RequestBody для того, что вы пытаетесь сделать. Вы можете использовать обычные функции Spring MVC, поэтому ваш метод контроллера будет выглядеть так:
@ResponseBody
public WebResponse<Boolean> updateEUSettings(
Locale locale,
@Valid EUPSettingsWrapper endUserPortalSettingsWrapper,
@RequestParam(value = "file1", required = true) MultipartFile logo
) {
}
Клиент, который отправляет запрос этому контроллеру, должен иметь форму с enctype="multipart/form-data"
.
В своем тесте Spring MVC вы бы написали что-то вроде этого:
getMockMvc().perform(fileUpload(uri).file("file1", "some-content".getBytes())
.param("someEuSettingsProperty", "someValue")
.param("someOtherEuSettingsProperty", "someOtherValue")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.MULTIPART_FORM_DATA))
.andExpect(status().isOk());
Ответ 2
Добавьте дополнительный bean в свой spring -servlet.xml, чтобы добавить поддержку для многостраничного запроса.
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
Также не забудьте добавить зависимость для commons-fileupload jar
Ответ 3
Я не мог найти способ использовать @RequestBody.
Однако вы можете сделать что-то вроде этого:
@RequestMapping(value = "/uploadStuff", method = RequestMethod.POST)
public MyViewDto doStuff(@RequestPart("json") @Valid MyDto dto,
@RequestPart("file") MultipartFile file) { ... }
Вы можете проверить это следующим образом:
MockMultipartFile jsonFile = new MockMultipartFile("json", "",
"application/json", "{}".getBytes());
MockMultipartFile dataFile = new MockMultipartFile("file", "foo.zip", "application/octet-stream", bytes);
mockMvc.perform(fileUpload("/uploadStuff")
.file(dataFile)
.file(jsonFile))
.andExpect(status().isOk());
Ответ 4
Для Spring 4 и более поздних версий вы можете сделать следующее, чтобы получить полный объект:
public ResponseEntity<Object> upload(@Payload EUPSettingsWrapper wrapper) {
}
Примечание: также должен работать без тега
public ResponseEntity<Object> upload(EUPSettingsWrapper wrapper) {
}
Ответ 5
Спасибо @JasonGlez, ответ, который работал для меня: публичная загрузка ResponseEntity (оболочка EUPSettingsWrapper) {
}
Ответ 6
Я немного потрудился с этим и закончил прохождение как простые параметры. Отлично, если у вас нет лота, чтобы передать ваш запрос:
myMethod(@RequestParam("file") MultipartFile myFile,
@RequestParam("param1") Float param1, @RequestParam("param2") String param2 {}