By default spring-boot is using StandardServletMultipartResolver to take care of multipart/form-data requests, although the assumption there is that a multipart/form-data request will be submitted as a POST request.
So If you are trying to submit a multipart/form-data using POST everything works perfectly fine out of the box.
But, if you need to submit a multipart/form-data as part of a PUT request, which is what we needed to do in order to be able to send an Image (i.e a company’s logo) as part of a company’s update here is the error that you would get from spring boot:
java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
The reason for this error as I mentioned earlier is that spring boot only expects a multipart/form-data as part of a POST request.
To fix this issue
Here is what we did in our application context, which is basically allowing the default resolver to also accept PUT requests:
@Bean public MultipartResolver multipartResolver() { return new StandardServletMultipartResolver() { @Override public boolean isMultipart(HttpServletRequest request) { String method = request.getMethod().toLowerCase(); //By default, only POST is allowed. Since this is an 'update' we should accept PUT. if (!Arrays.asList("put", "post").contains(method)) { return false; } String contentType = request.getContentType(); return (contentType != null &&contentType.toLowerCase().startsWith("multipart/")); } }; }
And here is how our REST controller looked like in this case (just for reference):
@Transactional @PreAuthorize("hasAnyRole('COMPANY.CREATE', 'COMPANY.EDIT')") @RequestMapping(value="/companies/{id}", method=RequestMethod.PUT , consumes=MULTIPART_FORM_DATA) public CompanyVO updateCompany(@PathVariable String id, @RequestParam(required=false, value="file") MultipartFile file, @RequestParam("data") String companyJsonStr) throws IOException { CompanyVO inputCompany = fromJsonString(companyJsonStr, CompanyVO.class); Company company = findCompany(id); setCompanyAttributes(inputCompany, company, file); companyDao.save(company); return convertToCompanyVO(company); }
That’s all you have to do and everything works for PUT just like POST.
About The Author: Mohammad Zolmajd
More posts by Mohammad Zolmajd