Server code for handling a file upload made by HttpClient - java

I have a Java HttpClient that executes the following code:
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://exampleutl.com/upload/");
File file = new File("C:/src_path/binary.doc");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.STRICT);
FileBody fileBody = new FileBody(file); //image should be a String
builder.addPart("file", fileBody);
post.setEntity(builder.build());
client.execute(post);
I cannot figure out what the server method mapped to the /upload/ path should look like.
The server that accepts this file upload request is Spring 4.0. Something like this:
#RequestMapping(method = RequestMethod.POST, value = "/upload/")
public #ResponseBody String saveUpload(UploadDto dto) throws IOException,ServletException {
File file = new File("C:/dest_path/" + dto.getFile().getOriginalFilename());
FileUtils.writeByteArrayToFile(file, dto.getFile().getBytes());
return "success";
}
The above server method gets called by the client.execute() but the UploadDto is empty.
Here is the UploadDto:
public class UploadDto {
private MultipartFile file;
public MultipartFile getFile() {
return file;
}
public void setFile(MultipartFile file) {
this.file = file;
}
}
Any assistance would be greatly appreciated!

You seem to be missing a MultipartResolver bean from your Spring servlet context. Something like
#Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
return multipartResolver;
}
You're sending your request to
HttpPost post = new HttpPost("http://exampleutl.com/upload/");
Assuming your context path is ROOT, ie. empty, your handler method should be mapped to /upload.
#RequestMapping(method = RequestMethod.POST, value = "/upload")

The ultimate answer was that the server method should look like this:
#RequestMapping(method = RequestMethod.POST, value = "/upload/")
public #ResponseBody String saveUpload(#RequestParam("file") final MultipartFile mpf) throws IOException, ServletException, FileUploadException {
File file = new File("C:/dest_path/" + mpf.getOriginalFilename());
FileUtils.writeByteArrayToFile(file, mpf.getBytes());
return "success";
}
As mentioned by Sotirios Delimanois the MultipartResolver is indeed a required part of the solution as well:
#Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
return multipartResolver;
}

Related

return ByteArrayResource in spring restcontroller response

I'm trying to download a file using my restController, but it always return this error :
java.io.FileNotFoundException: Byte array resource [resource loaded from byte array] cannot be resolved to URL
at org.springframework.core.io.AbstractResource.getURL(AbstractResource.java:90) ~[spring-core-4.2.2.RELEASE.jar:4.2.2.RELEASE]
then it downloads a file that has something like this :
{"byteArray":"JVBERi0xLjQKJeL....
here's my restController :
#Api("products")
#RestController
#RequestMapping("/v1/products")
public class DocumentApi extends storeApi {
#ApiOperation("GET download document")
#RequestMapping(value = "/temp", method = RequestMethod.GET)
#ResponseStatus(code = HttpStatus.OK)
public ResponseEntity<ByteArrayResource> downloadDocument(
#RequestParam(value = "id", required = true) Long idInscription) throws IOException {
String signedFilePAth = "C:/APPLIS/signedTemp/5982312957957647037_signed.pdf"
return ResponseEntity
.ok()
.contentLength(contentLength)
.contentType(
MediaType.parseMediaType("application/pdf"))
.body(new
ByteArrayResource(Files.readAllBytes(Paths.get(signedFilePAth))));
}
}
and here's my spring configuration :
protected MappingJackson2HttpMessageConverter jacksonMessageConverter() {
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// Registering Hibernate4Module to support lazy objects
mapper.registerModule(new Hibernate4Module());
messageConverter.setObjectMapper(mapper);
return messageConverter;
}
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
return arrayHttpMessageConverter;
}
private List<MediaType> getSupportedMediaTypes() {
List<MediaType> list = new ArrayList<MediaType>();
list.add(MediaType.APPLICATION_OCTET_STREAM);
list.add(MediaType.parseMediaType("application/pdf"));
return list;
}
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(jacksonMessageConverter());
converters.add(byteArrayHttpMessageConverter());
super.configureMessageConverters(converters);
}
what seems to be the problem ? how can i solve this ?
nb : I don't know if this is related, but my swagger-ui.html doesn't work (it shows a blank page) while v2/api-docs/ works fine
Try returning array of bytes:
#RequestMapping(value = "/temp", method = RequestMethod.GET)
public #ResponseBody byte[] downloadDocument(
#RequestParam(value = "id", required = true) Long idInscription) throws IOException {
FileInputStream signedFileInputStream = new FileInputStream(signedFilePAth);
byte[] doc = IOUtils.toByteArray(fis);
return doc;
}
IOUtils is from org.apache.commons.io.IOUtils.
It seems that the response content type definition is missing from your code.
The following code snippet returns with an image content which is displayed by web browser. It is a Jersy code but you can adopt it to Spring:
#GET
#Path("/{image-uuid}")
#Produces("images/jpg")
public Response getImage(#PathParam("uuid") final String uuid) throws IOException {
byte[] content = imageDao.getImage(uuid);
if (Objects.isNull(content )) {
throw new ImageNotFoundError(uuid);
}
ByteArrayInputStream stream = new ByteArrayInputStream(content);
return Response.ok(stream).build();
}

How to read Long blob from mysql in java? [duplicate]

I'm getting image data (as byte[]) from DB. How to return this image in #ResponseBody ?
EDIT
I did it without #ResponseBody using HttpServletResponse as method parameter:
#RequestMapping("/photo1")
public void photo(HttpServletResponse response) throws IOException {
response.setContentType("image/jpeg");
InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");
IOUtils.copy(in, response.getOutputStream());
}
Using #ResponseBody with registered org.springframework.http.converter.ByteArrayHttpMessageConverter converter as #Sid said doesn't work for me :(.
#ResponseBody
#RequestMapping("/photo2")
public byte[] testphoto() throws IOException {
InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");
return IOUtils.toByteArray(in);
}
if you are using Spring version of 3.1 or newer you can specify "produces" in #RequestMapping annotation. Example below works for me out of box. No need of register converter or anything else if you have web mvc enabled (#EnableWebMvc).
#ResponseBody
#RequestMapping(value = "/photo2", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
public byte[] testphoto() throws IOException {
InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");
return IOUtils.toByteArray(in);
}
With Spring 4.1 and above, you can return pretty much anything (such as pictures, pdfs, documents, jars, zips, etc) quite simply without any extra dependencies. For example, the following could be a method to return a user's profile picture from MongoDB GridFS:
#RequestMapping(value = "user/avatar/{userId}", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<InputStreamResource> downloadUserAvatarImage(#PathVariable Long userId) {
GridFSDBFile gridFsFile = fileService.findUserAccountAvatarById(userId);
return ResponseEntity.ok()
.contentLength(gridFsFile.getLength())
.contentType(MediaType.parseMediaType(gridFsFile.getContentType()))
.body(new InputStreamResource(gridFsFile.getInputStream()));
}
The things to note:
ResponseEntity with InputStreamResource as a return type
ResponseEntity builder style creation
With this method you dont have to worry about autowiring in the HttpServletResponse, throwing an IOException or copying stream data around.
In addition to registering a ByteArrayHttpMessageConverter, you may want to use a ResponseEntity instead of #ResponseBody. The following code works for me :
#RequestMapping("/photo2")
public ResponseEntity<byte[]> testphoto() throws IOException {
InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
return new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED);
}
By using Spring 3.1.x and 3.2.x, this is how you should do it:
The controller method:
#RequestMapping("/photo2")
public #ResponseBody byte[] testphoto() throws IOException {
InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");
return IOUtils.toByteArray(in);
}
And the mvc annotation in servlet-context.xml file:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>image/jpeg</value>
<value>image/png</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
In addition to a couple of answers here a few pointers (Spring 4.1).
Incase you don't have any messageconverters configured in your WebMvcConfig, having ResponseEntity inside your #ResponseBody works well.
If you do, i.e. you have a MappingJackson2HttpMessageConverter configured (like me) using the ResponseEntity returns a org.springframework.http.converter.HttpMessageNotWritableException.
The only working solution in this case is to wrap a byte[] in the #ResponseBody as follows:
#RequestMapping(value = "/get/image/{id}", method=RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
public #ResponseBody byte[] showImageOnId(#PathVariable("id") String id) {
byte[] b = whatEverMethodUsedToObtainBytes(id);
return b;
}
In this case do rememeber to configure the messageconverters properly (and add a ByteArrayHttpMessageConverer) in your WebMvcConfig, like so:
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(mappingJackson2HttpMessageConverter());
converters.add(byteArrayHttpMessageConverter());
}
#Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper);
return converter;
}
#Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
return arrayHttpMessageConverter;
}
private List<MediaType> getSupportedMediaTypes() {
List<MediaType> list = new ArrayList<MediaType>();
list.add(MediaType.IMAGE_JPEG);
list.add(MediaType.IMAGE_PNG);
list.add(MediaType.APPLICATION_OCTET_STREAM);
return list;
}
I prefere this one:
private ResourceLoader resourceLoader = new DefaultResourceLoader();
#ResponseBody
#RequestMapping(value = "/{id}", produces = "image/bmp")
public Resource texture(#PathVariable("id") String id) {
return resourceLoader.getResource("classpath:images/" + id + ".bmp");
}
Change the media type to what ever image format you have.
In your application context declare a AnnotationMethodHandlerAdapter and registerByteArrayHttpMessageConverter:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<util:list>
<bean id="byteArrayMessageConverter" class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
</util:list>
</property>
</bean>
also in the handler method set appropriate content type for your response.
#RequestMapping(value = "/get-image",method = RequestMethod.GET)
public ResponseEntity<byte[]> getImage() throws IOException {
RandomAccessFile f = new RandomAccessFile("/home/vivex/apache-tomcat-7.0.59/tmpFiles/1.jpg", "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
return new ResponseEntity<byte[]>(b, headers, HttpStatus.CREATED);
}
Worked For Me.
You should specify the media type in the response. I'm using a #GetMapping annotation with produces = MediaType.IMAGE_JPEG_VALUE. #RequestMapping will work the same.
#GetMapping(value="/current/chart",produces = MediaType.IMAGE_JPEG_VALUE)
#ResponseBody
public byte[] getChart() {
return ...;
}
Without a media type, it is hard to guess what is actually returned (includes anybody who reads the code, browser and of course Spring itself). A byte[] is just not specific. The only way to determine the media type from a byte[] is sniffing and guessing around.
Providing a media type is just best practice
It's work for me in Spring 4.
#RequestMapping(value = "/image/{id}", method = RequestMethod.GET)
public void findImage(#PathVariable("id") String id, HttpServletResponse resp){
final Foto anafoto = <find object>
resp.reset();
resp.setContentType(MediaType.IMAGE_JPEG_VALUE);
resp.setContentLength(anafoto.getImage().length);
final BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(anafoto.getImageInBytes()));
try {
FileCopyUtils.copy(in, resp.getOutputStream());
resp.flushBuffer();
} catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Non of the answers worked for me, so I've managed to do it like that:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("your content type here"));
headers.set("Content-Disposition", "attachment; filename=fileName.jpg");
headers.setContentLength(fileContent.length);
return new ResponseEntity<>(fileContent, headers, HttpStatus.OK);
Setting Content-Disposition header I was able to download the file with the #ResponseBody annotation on my method.
This is how I do it with Spring Boot and Guava:
#RequestMapping(value = "/getimage", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
public void getImage( HttpServletResponse response ) throws IOException
{
ByteStreams.copy( getClass().getResourceAsStream( "/preview-image.jpg" ), response.getOutputStream() );
}
In spring 4 it's very easy you don't need to make any changes in beans. Only mark your return type to #ResponseBody.
Example:-
#RequestMapping(value = "/image/{id}")
public #ResponseBody
byte[] showImage(#PathVariable Integer id) {
byte[] b;
/* Do your logic and return
*/
return b;
}
I think you maybe need a service to store file upload and get that file.
Check more detail from here
1) Create a Storage Sevice
#Service
public class StorageService {
Logger log = LoggerFactory.getLogger(this.getClass().getName());
private final Path rootLocation = Paths.get("upload-dir");
public void store(MultipartFile file) {
try {
Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename()));
} catch (Exception e) {
throw new RuntimeException("FAIL!");
}
}
public Resource loadFile(String filename) {
try {
Path file = rootLocation.resolve(filename);
Resource resource = new UrlResource(file.toUri());
if (resource.exists() || resource.isReadable()) {
return resource;
} else {
throw new RuntimeException("FAIL!");
}
} catch (MalformedURLException e) {
throw new RuntimeException("FAIL!");
}
}
public void deleteAll() {
FileSystemUtils.deleteRecursively(rootLocation.toFile());
}
public void init() {
try {
Files.createDirectory(rootLocation);
} catch (IOException e) {
throw new RuntimeException("Could not initialize storage!");
}
}
}
2) Create Rest Controller to upload and get file
#Controller
public class UploadController {
#Autowired
StorageService storageService;
List<String> files = new ArrayList<String>();
#PostMapping("/post")
public ResponseEntity<String> handleFileUpload(#RequestParam("file") MultipartFile file) {
String message = "";
try {
storageService.store(file);
files.add(file.getOriginalFilename());
message = "You successfully uploaded " + file.getOriginalFilename() + "!";
return ResponseEntity.status(HttpStatus.OK).body(message);
} catch (Exception e) {
message = "FAIL to upload " + file.getOriginalFilename() + "!";
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(message);
}
}
#GetMapping("/getallfiles")
public ResponseEntity<List<String>> getListFiles(Model model) {
List<String> fileNames = files
.stream().map(fileName -> MvcUriComponentsBuilder
.fromMethodName(UploadController.class, "getFile", fileName).build().toString())
.collect(Collectors.toList());
return ResponseEntity.ok().body(fileNames);
}
#GetMapping("/files/{filename:.+}")
#ResponseBody
public ResponseEntity<Resource> getFile(#PathVariable String filename) {
Resource file = storageService.loadFile(filename);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"")
.body(file);
}
}
When using produces with MediaType.IMAGE_JPEG_VALUE, make sure that you are returning byte[], but not Byte[]. Very strange, but spring cannot convert it and raises an exception: no converter found.

Spring controller image download in byte[] instead base64

I encountered a problem with downloading grid fs stored image via spring controller. When trying to open the downloaded file the image viewer says that it is corrupted, it turns out that the image is in base64 format.
There is the controller part:
#Override
#RequestMapping(value = "/image_download", method = RequestMethod.GET)
public ResponseEntity<byte[]> downloadImage(...) throws IOException {
final GridFSDBFile image = getImageFromGrifFs(...);
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf(image.getContentType()));
headers.setContentDispositionFormData("attachment", image.getFileName());
final byte[] content = IOUtils.toByteArray(image.getInputStream());
return new ResponseEntity<>(content, headers, HttpStatus.OK);
}
Spring version is 4.3.11.
And here are the message converters:
#Override
public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter());
converters.add(byteArrayHttpMessageConverter());
super.configureMessageConverters(converters);
}
#Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
final ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
return arrayHttpMessageConverter;
}
private List<MediaType> getSupportedMediaTypes() {
final List<MediaType> list = new ArrayList<>();
list.add(MediaType.IMAGE_JPEG);
list.add(MediaType.IMAGE_PNG);
list.add(MediaType.IMAGE_GIF);
list.add(MediaType.APPLICATION_OCTET_STREAM);
return list;
}
I also tried using InputStreamResource the following way in the controller:
return ResponseEntity.ok()
.contentLength(image.getLength())
.contentType(MediaType.parseMediaType(image.getContentType()))
.body(new InputStreamResource(image.getInputStream()));
But got the exception:
Could not write content: No serializer found for class com.mongodb.gridfs.GridFSDBFile$MyInputStream
Any help appreciated. Thank you.
After I'd done some more digging I found good explanation: https://stackoverflow.com/a/44943494/2421204
And indeed adding (produces = "image/jpeg") to RequestMapping solved the issue.
#RequestMapping(value = "/image_download", method = RequestMethod.GET, produces = "image/jpeg")
The images that are downloaded are in binary.

HTTP 406 downloading a file with rest call

I followed this tutorial to implement rest API with Spring Boot for downloading files (xml format).
My controller class is as follows:
#RestController
public class RistoreController {
#Autowired
private RistoreService ristoreService;
#RequestMapping(
value = "/ristore/foundation/{trf}",
method = RequestMethod.GET,
produces = "application/xml")
public ResponseEntity<InputStream> getXMLById(#PathVariable("trf") String trf) throws IOException {
InputStream inputStream = ristoreService.findByTRF(trf);
return ResponseEntity
.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(inputStream);
}
}
I have service interface RistoreService autowired in the controller and Bean class for that service looks like this:
#Service
public class RistoreServiceBean implements RistoreService {
public InputStream findByTRF(String trf) throws IOException {
String filePath = "/Users/djiao/Box Sync/Work/Projects/RIStore/foundation/foundation_new/" + trf + ".xml";
File file = new File(filePath);
return new FileInputStream(file);
}
}
I tested the application using the following curl command:
curl -i -H "Accept: application/xml" http://localhost:8080/ristore/foundation/TRF133672_1455294493597
However, I got 406 error, "Not Acceptable". Something wrong with the file format?
Try to change the definition of the controller that way
#RequestMapping(value = "/ristore/foundation/{trf}", method = RequestMethod.GET, produces = "application/xml")
public ResponseEntity<InputStreamResource> downloadXMLFile(#PathVariable("trf") String trf)
throws IOException {
// Optinal headers configuration
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
// get the inputStream
InputStream xmlFileInputStream = ristoreService.findByTRF(trf);
return ResponseEntity
.ok()
.headers(headers)
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(new InputStreamResource(xmlFileInputStream));
}
Then your service class would be :
#Service
public class RistoreServiceBean implements RistoreService {
public InputStream findByTRF(String trf) throws IOException {
String filePath = "/Users/djiao/Box Sync/Work/Projects/RIStore/foundation/foundation_new/" + trf + ".xml";
File file = new File(filePath);
return new FileInputStream(file);
}
}
406 Not Acceptable
The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request.
That means that the inputstream you return must be considered as a resource as soon as you have a REST controller.
The following two lines in your code contradict each other:
.contentType(MediaType.parseMediaType("application/octet-stream"))
and
produces = "application/xml")

SPRING - REST Template - Upload File using File Input Stream & Other primitve data

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!!
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.
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.

Categories