A REST service that can use both JSON and Multipart Form

I need to create a method in Spring MVC that can handle JSON and Multipart Form requests.

This is my method signature:

@RequestMapping(value = { "/upload_image" }, method = RequestMethod.POST) public @ResponseBody void uploadImage(final ImageDTO image) 

The ImageDTO class is as follows:

 public class ImageDTO { private String imageUrl; private Long imageId; private MultipartFile image; public String getImageUrl() { return imageUrl; } public void setImageUrl(final String url) { this.imageUrl = url; } public Long getImageId() { return imageId; } public void setImageId(final Long imageId) { this.imageId = imageId; } public MultipartFile getImage() { return image; } public void setImage(MultipartFile image) { this.image = image; } } 

So, the scenario is that I need to support two scenarios: 1. Download the download from the form where the Content-Type is multi-part (all DTO members are non-zero) 2. Upload the image using JSON using ONLY imageUrl. In this case, the request body is as follows:

 { "imageId":"1236", "imageUrl":"http://some.image.url", "image":null } 

The current implementation handles a multi-page request well, but when sending JSON, the ImageDTO object contains NULL in all its members.

Is it possible for the same method to process both types of content?

Thanks.

+6
source share
3 answers

To get JSON, you need to tag ImageDTO with @RequestBody

 @RequestMapping(value = { "/upload_image" }, method = RequestMethod.POST) public @ResponseBody void uploadImage(final @RequestBody ImageDTO image) 
+1
source

And faced with a similar situation, and that's what I came up with. Both are not so clean, but they work just fine. You need to send the client a multi-page request :

Note. The data type of the variable to store the file is InputStream . You must modify it accordingly.

  • This is useful in cases where you do not know the number of files that you receive a request from you.

     // imports import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; // code flow // HttpServletRequest request final FileItemFactory factory = new DiskFileItemFactory(); final ServletFileUpload fileUpload = new ServletFileUpload(factory); List items = null; private Map<String, InputStream> fileMap = new HashMap<String, InputStream>(); if (ServletFileUpload.isMultipartContent(request)) { // get the request content and iterate through items = fileUpload.parseRequest(request); if (items != null) { final Iterator iter = items.iterator(); while (iter.hasNext()) { final FileItem item = (FileItem) iter.next(); final String fieldName = item.getFieldName(); final String fieldValue = item.getString(); // this is for non-file fields if (item.isFormField()) { switch (fieldName) { case "imageId" : // set inside your DTO field break; // do it for other fields } } else { // set the image in DTO field } } } } 
  • In this case, you will have to deal with a fixed number of field shapes. I implemented the ReST method as follows:

     @Path("/upload") @POST @Consumes(MediaType.MULTIPART_FORM_DATA) public ResponseDTO upload(FormDataMultiPart multiPartData) { // non-file fields final String imageId = multiPartData.getField("imageId").getValue(); // for file field final FormDataBodyPart imagePart = multiPartData.getField("image"); final ContentDisposition imageDetails= imagePart.getContentDisposition(); final InputStream imageDoc = imagePart.getValueAs(InputStream.class); // set the retrieved content in DTO } 
+1
source

I had the same result - NULL in all DTO members until I entered the @ModelAttribute annotation. Now everything works fine, here is the working code:

Controller Method :

 @RequestMapping(value = "/save", method = RequestMethod.POST, consumes = { "multipart/form-data" }) public void create(@Valid @ModelAttribute("entryForm") final EntryDTO entryDTO, final BindingResult validationResult) throws FormValidationError { validate(entryDTO, validationResult); entryService.save(entryDTO); } 

DTO

 public class EntryDTO { private String phrase; private String translation; private MultipartFile imageFile; } 

The form

 <form method="post" name="entryForm" action="http://localhost:8080/save" enctype="multipart/form-data"> <p><input type="text" name="phrase" value="test"/> phrase</p> <p><input type="text" name="translation" value=""/> translation</p> <p><input type="file" name="imageFile"/></p> <p><input type="submit"/></p> </form> 

Please note that the form is called "entryForm" and, accordingly, @ModelAttribute ("entryForm").

0
source

Source: https://habr.com/ru/post/981335/


All Articles