0

I know this has been discussed many times and I have searched a lot on Google / Stackoverflow, but can't seem to get it working.

I have a Spring MVC web application, JSP sends media file along with some text fields, the controller captures the Input Stream and other form data (some text fields), and creates a POJO object of type FileUploadRequest. The complete data (file + text fields) have to be passed as-is to another service (third party service) for upload.

I am using Spring REST Template to connect to the third part service. Below are the code snippets:

RestTemplate Initialization (Java Config)

@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;
}

Controller Code:

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); 
}

POJO Class:

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

uploadFileToService method implementation

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);
}

Now, when I run my application, I get the following error:

Caused by: java.lang.UnsupportedOperationException: getBody not supported at org.springframework.http.client.HttpComponentsStreamingClientHttpRequest.getBodyInternal(HttpComponentsStreamingClientHttpRequest.java:84) at org.springframework.http.client.AbstractClientHttpRequest.getBody(AbstractClientHttpRequest.java:47) at org.springframework.http.converter.FormHttpMessageConverter.writeMultipart(FormHttpMessageConverter.java:299) at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:238) at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:87) at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:777) at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:566) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:529) at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:447)

Please let me know what is it that I am missing, I am not able to figure out the issue.

If further details are needed, I can share

Thanks!!

0

2 Answers 2

0

Use MultipartFile from Spring Web, then just use @RequestParam("file") MultipartFile file as an argument in your controller. Then you will have access to the stream along with all other properties that came with the upload.

Sign up to request clarification or add additional context in comments.

1 Comment

Will that make any difference, I mean using MultipartFile in controller will only remove some code in controller (where form fields are being retrieved from request and set into POJO). Is my understanding correct, or any other changes are needed?
0

So, looks like I resolved it. The issue is due to a bug on Spring 4.1.1 Release. It got resolved in 4.2.0 Changed the pom dependency to use 4.2.0 and now it works fine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.