SPRING - Шаблон REST - Загрузить файл с использованием потока ввода файла и других примитивных данных

Я знаю, что это обсуждалось много раз, и я много искал в Google/Stackoverflow, но не могу заставить его работать.

У меня есть веб-приложение Spring MVC, JSP отправляет медиафайл вместе с некоторыми текстовыми полями, контроллер захватывает входной поток и другие данные формы (некоторые текстовые поля) и создает объект POJO типа FileUploadRequest. Полные данные (файл + текстовые поля) должны быть переданы как есть другой службе (сторонней службе) для загрузки.

Я использую шаблон Spring REST для подключения к сторонней службе. Ниже приведены фрагменты кода:

Инициализация RestTemplate (конфигурация Java)

@Bean
public ClientHttpRequestFactory httpRequestFactory() {
    final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient());
    requestFactory.setBufferRequestBody(false);
    return requestFactory;
}

@Bean
public RestTemplate getRestTemplate() {
    final RestTemplate restTemplate = new RestTemplate();
    restTemplate.setRequestFactory(httpRequestFactory()); // apache http library
    restTemplate.setMessageConverters(getMessageConverters());
}


private List<HttpMessageConverter<?>> getMessageConverters() {
    final List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
    final FormHttpMessageConverter e = new FormHttpMessageConverter();
    e.addPartConverter(new MappingJackson2HttpMessageConverter());
    converters.add(e);
    return converters;
}

@Bean
public CommonsMultipartResolver multipartResolver() {
    final CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
    return commonsMultipartResolver;
}

Код контроллера:

public APPResponse uploadFile(final HttpServletRequest request) {
    final FileUploadRequest uploadRequest = new FileUploadRequest();
    final List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
    for (final FileItem item : items) {
         if (item.isFormField()) {
             String fieldValue = item.getString();
             uploadRequest.setEnabled(Boolean.valueOf(fieldValue));
         } else {
             String fileName = FilenameUtils.getName(item.getName());
             InputStream fileContent = item.getInputStream();
             uploadRequest.setFileName(fileName);
             uploadRequest.setFileStream(fileContent);
         }
    }
    uploadFileToService(uploadRequest); 
}

Класс ПОЖО:

public class FileUploadRequest {
    private String fileName;
    private InputStream fileStream;
    private boolean enabled;
    // getter setters...
}

реализация метода uploadFileToService

public FileUploadResponse uploadFileToService(final FileUploadRequest uploadRequest) {
    final HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.MULTIPART_FORM_DATA);

    final String url = <URL where the file is to passed as is>;
    MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>();
    parameters.set("Content-Type","multipart/form-data");
    parameters.add("file", uploadRequest.getFileStream());
    parameters.add("someOtherParam", uploadRequest.isEnabled());

    final HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(
            parameters, headers);
    final ResponseEntity<T> exchange = template.exchange(url,
                HttpMethod.POST, httpEntity, FileUploadResponse.class);
}

Теперь, когда я запускаю свое приложение, я получаю следующую ошибку:

Вызвано: java.lang.UnsupportedOperationException: getBody не поддерживается в org.springframework.http.client.HttpComponentsStreamingClientHttpRequest.getBodyInternal(HttpComponentsStreamingClientHttpRequest.java:84) в org.springframework.http.client.AbstractClientHttpRequest.getBody(AbstractClientHttpRequest.java:47) в org.springframework.http.converter.FormHttpMessageConverter.writeMultipart(FormHttpMessageConverter.java:299) в org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:238) в org.springframework.http.converter.FormHttpMessageConverter.write (FormHttpMessageConverter.java:87) в org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:777) в org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:566) в org. springframework.web.client.RestTemplate.execute(RestTemplate.java:529) в org.springframework.web.client.Rest Template.exchange(RestTemplate.java:447)

Подскажите, пожалуйста, что мне не хватает, не могу разобраться.

Если нужны подробности, могу поделиться

Спасибо!!


person kaps    schedule 16.10.2015    source источник


Ответы (2)


Используйте MultipartFile из Spring Web, затем просто используйте @RequestParam("file") MultipartFile file в качестве аргумента в вашем контроллере. Затем у вас будет доступ к потоку вместе со всеми другими свойствами, которые были добавлены вместе с загрузкой.

person Tassos Bassoukos    schedule 16.10.2015
comment
Будет ли это иметь значение, я имею в виду, что использование MultipartFile в контроллере удалит только некоторый код в контроллере (где поля формы извлекаются из запроса и устанавливаются в POJO). Правильно ли я понимаю или нужны какие-то другие изменения? - person kaps; 16.10.2015

Итак, похоже, я решил это. Проблема связана с ошибкой в ​​выпуске Spring 4.1.1. Это было решено в 4.2.0. Изменена зависимость pom для использования 4.2.0, и теперь она работает нормально.

person kaps    schedule 16.10.2015