I am trying to merge two Spring based projects into one but I am having an issue with MultiPartResolver. Inside my merged application there are two classes that use uploaded POST methods using different upload methods.
One uses the HttpServletRequest to retrieve the uploaded file :
#RequestMapping(method = RequestMethod.POST)
public #ResponseBody void handleResult(HttpServletRequest request,
HttpServletResponse response)
and the other uses MultipartFile to get the file and another field called notes which is passed to the form:
#RequestMapping(method = RequestMethod.POST)
public #ResponseBody String handleFormUpload(#RequestParam("notes")
String notes, #RequestParam("file") MultipartFile file)
The code then references 'file' to process the uploaded file.
The problem I have is the MultipartFile class requires this in the applicationContext.xml:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="250000000"/>
</bean>
When this is in the applicationContext.xml file the original Servlet based method of posting fails. The POST request reaches this class but the file seems to have been stripped out as it processes it. As soon as I comment this out of the applicationContext.xml, the servlet method works again. However, the section of the code that uses the MultipartResolver now fails!
I do not have much experience of Spring but I'm trying my best to do this. I cannot work out how to prevent CommonsMultipartResolver from manipulating the POST files that are destined for the Servlet based class.
Can anybody help me?
Related
I am refactoring some legacy code used to upload files using Commons Fileupload and JSPs, to use Spring Controllers. Given that lots of the code for file uploads is based on Commons Fileupload, I want to reuse that code. The first attempt was made directly moving the code from the JSP to a Spring Controller, like this:
#RequestMapping(path = { "/my/file/upload/request/mapping" })
public ModelAndView myControllerMethod(HttpServletRequest request, HttpServletResponse response){
List<FileItem> items = null;
if (ServletFileUpload.isMultipartContent(request)) {
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
items = upload.parseRequest(request);
System.out.println("number of items: " + (items != null ? items.size() : "null"));
}
...
Although the program enters the if, recognizing it as a multipart request, this always shows number of items: 0.
I have included a MultipartViewResolver like this:
#Configuration
#EnableWebMvc
#SuppressWarnings("deprecation")
public class WebMvcConfiguration extends WebMvcConfigurerAdapter{
#Bean
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(maxFileUploadSizeBytes);
return multipartResolver;
}
but the result is the same with or without it.
As stated in many places (like here (Baeldung) and here (SO)), it seems that Commons Fileupload cannot read the multipart because it has already been read by Spring. So the solution seems to be to disable Spring multipart support. Many posts tell how to do that for Spring Boot but I have no idea about how to do that for raw Spring 5. Any idea about how to do it?
Note: I've also tried to get the multipart files using the Spring way, like this:
#RequestMapping(path = { "/my/file/upload/request/mapping" })
public ModelAndView myControllerMethod(#RequestParam MultipartFile file){
and even #RequestParam MultipartFile[] files but I obtain null files or empty files array respectively. Again, I've checked with Firefox console that the request being made is exactly the same as with the old JSP code, which worked, so the problem is not in the request being made.
You are missing the name of the request parameter to bind to.
Refer spring's java doc here
For example,
#RequestParam("file") MultipartFile multipartFile
"file" is the name of the request parameter in your JSP.
<input type="file" name="file"><br />
And make sure you are using POST method as well.
#RequestMapping(value = "/my/file/upload/request/mapping", method = RequestMethod.POST)
Make sure your form has the attribute, enctype="multipart/form-data";
<form enctype="multipart/form-data" >
</form>
afterwards your request param need to be corrected to ;
#RequestParam("file") MultipartFile file
not you can test using the following condition, and store the multipart in a byte array
if(file.isEmpty()){
byte [] bytefile= file.getBytes();
}
else{
logger.info("not caught");
}
I have a rest controller method that receive a multipart file parameter, I need to constraint the file size limit of it. I tried different optiones but it's not working yet for me. I´m using Apache Tomcat 8. I'm calling the rest method by a windows service.
Following the definition of the class and the method:
#Controller
public class MyClass{
...
}
#RequestMapping(value = "/path/method/param1/{param1}/param2/{param2}/",
method = RequestMethod.POST)
public ResponseEntity<String> method(DTO dto, #RequestParam("file") MultipartFile multipartFile){
...
}
Solutions tested:
Adding the following node in the web.xml file
<multipart-config>
<max-file-size>52428800</max-file-size>
<max-request-size>52428800</max-request-size>
<file-size-threshold>0<</file-size-threshold>
</multipart-config>
Adding maxPostSize and maxSwallowSize properties to the connector node in the server.xml file
Adding parameters of size to the .properties file
Adding the #MultipartConfig annotation in the controller class
Any idea or suggestions?
Check the spring-servlet.xml file, maybe there is a created bean of the class org.springframework.web.multipart.commons.CommonsMultipartResolver, it could be above of the rest of configurations or methods to handle this
In my controller when sending parameter as form-data, its receiving as null value.
When passing parameter as x-www-form-urlencoded, I am getting the value.
My controller is like the following:
#RequestMapping(value = "/getid", method = RequestMethod.POST)
public ServerResponse id(#RequestParam(value = "id", required = false) String id) {...}
If you need to send parameters are form-data then you need to add support for this in Spring,
Have a look at spring's documentation http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-multipart
Spring’s built-in multipart support handles file uploads in web
applications. You enable this multipart support with pluggable
MultipartResolver objects, defined in the
org.springframework.web.multipart package. Spring provides one
MultipartResolver implementation for use with Commons FileUpload and
another for use with Servlet 3.0 multipart request parsing.
By default, Spring does no multipart handling, because some developers
want to handle multiparts themselves. You enable Spring multipart
handling by adding a multipart resolver to the web application’s
context. Each request is inspected to see if it contains a multipart.
If no multipart is found, the request continues as expected. If a
multipart is found in the request, the MultipartResolver that has been
declared in your context is used. After that, the multipart attribute
in your request is treated like any other attribute.
This is an example of how to use CommonsMultipartResolver
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="100000"/>
</bean>
Of course you also need to put the appropriate jars in your classpath
for the multipart resolver to work. In the case of the
CommonsMultipartResolver, you need to use commons-fileupload.jar.
I have configured the access decision manager to check a request before being processed by the servlet the key line is:-
HttpServletRequest request = (HttpServletRequest) RequestContextHolder.currentRequestAttributes().getRequest();
All good. However when the request is enctype="multipart/form-data" how do I get hold of the MultipartHttpServletRequest when RequestContextHolder.currentRequestAttributes().getRequest() only returns HttpServletRequest?
I am using spring 2.5.
MultipartHttpServletRequest is n Spring-specific interface for handling multipart form submissions. The default implementation is DefaultMultipartHttpServletRequest, which has a constructor that takes a HttpServletRequest.
So:
HttpServletRequest originalRequest = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
MultipartHttpServletRequest multiPartRequest = new DefaultMultipartHttpServletRequest(originalRequest);
Apart from having
<form method=<method> action=<url> enctype="multipart/form-data"></form>
you have to have
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
in your spring configuration file.
Here is nice tutorial on the same
http://techdive.in/spring/spring-file-upload
Have you tried casting to MultipartHttpServletRequest?
If you are using spring-mvc, make sure you put this line
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
in your app-config.xml.
This worked for me.
I don't think you can get DefaultMultipartHttpServletRequest from RequestContextHolder.
DefaultMultipartHttpServletRequest really implements HttpServletRequest.
But there're 2 request instances if you use CommonsMultipartResolver. One is DefaultMultipartHttpServletRequest instance, and another is HttpServletRequest instance.
Actually I don't know how to get the first instance from RequestContextHolder. You can get the second instance from it.
I am trying to upload files with apache common-fileupload and spring, and my form contains fields also. but when i am trying to submit always getting null pointer exception
so now using Multipartstream for getting solution on the same.
#RequestMapping(value="/uploadfile.do", method = RequestMethod.POST)
public ModelAndView uploadFile(#ModelAttribute("frm") ReceiptForm form, BindingResult result, HttpServletRequest request){
System.out.println("---"+form.getProductName());
System.out.println("---"+form.getRfile());
ModelAndView mav = new ModelAndView("receipt/upload");
mav.addObject("command", form);
return mav;
}
The following example shows how to use the CommonsMultipartResolver:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="100000"/>
By adding this to your spring config your controllers should pickup file uploads
or try google