Spring MVC file upload is passing null to the controller - java

i've a spring MVC application and when i try to upload a multipart file, a null value is passed to the controller. all the other text parameters are passed properly only the file input is passed as null. I've included the MultipartResolver bean and commons-io plus commons-fileupload dependencies in my project. i've checked it's passed in the browser's request but it's not bound in the modelAttribute.
here is a snippet code from my view
<form:form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/profile/secure/saveIdentity" commandName="profileModel">
<span><b>Upload your passport photo</b></span>
<form:input path="passportPhotograph" type="file" id="passportPhoto"/>
</form:form>
and here is a snippet from my controller method
#RequestMapping(value = "/secure/saveIdentity", method = RequestMethod.POST)
public ModelAndView saveIdentity(#ModelAttribute("profileModel") #Valid ProfileModel profileModel,HttpServletRequest request){
MultipartFile photo = profileModel.getPassportPhotograph();
if(photo != null){ do something.... }
}
here is my ProfileModel.java class snippet
public class ProfileModel{
private MultipartFile passportPhotograph;
public MultipartFile getPassportPhotograph() {
return passportPhotograph;
}
public void setPassportPhotograph(MultipartFile passportPhotograph) {
this.passportPhotograph = passportPhotograph;
}
............
}
And in my dispatcher-servlet file I have declared MultipartResolver bean:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="99999999999"/>
</bean>
and finally in my build.gradle file i added these dependencies
compile('commons-io:commons-io:2.0.1')
compile('commons-fileupload:commons-fileupload:1.3.1')
after all this it's passing null to my controller even though it's included in the HttpServletRequest. what should i do to fix this. Thanks in advance for you help.

you need to use #RequestMapping(value = "/secure/saveIdentity", method = RequestMethod.POST, headers = ("content-type=multipart/*"), produces = "application/json", consumes = "image/*").

Solved my issue by using the StandardServletMultipartResolver which comes with the spring web framework. But you have to use Servlet version 3.0+ for this to work.

This sample code. point is input tag name binding file in model. maybe you need library json and file. ex) commons-io, commons-fileupload and jackson, gson use to parsing in controller.
HTML
<form:form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/profile/secure/saveIdentity">
<span><b>Upload your passport photo</b></span>
<form:input type="file" name="file"/>
</form:form>
Controller
#RequestMapping(value = "test", method = RequestMethod.POST)
public String testFormData(FileAndContentModel model) {
// break point and check model.
return "success";
}
Model
public class FileAndContentModel {
private MultipartFile file;
public FileAndContentModel () {
}
// getter, setter
}

This is not the solution, I just type here because is easier to read than a comment. Please try the minimum requeriment, just upload a file and verify if works.
Form:
<form:form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/profile/secure/saveIdentity">
<span><b>Upload your passport photo</b></span>
<input name="file" type="file" id="passportPhoto"/>
</form:form>
Controller:
#RequestMapping(value = "/secure/saveIdentity", method = RequestMethod.POST)
public void saveIdentity(#RequestParam("file") MultipartFile file) {
//please verify here if the file is null

Related

HTTP Status 400 - Spring MVC Error

I´m developing a webapp with Maven and Spring MVC. When submitting a button the HTTP Status 400- Error appears. The descriptions says: "The request sent by the client was syntactically incorrect."
This is my .jsp:
<body>
<form:form modelAttribute="circleUpForm" method="POST" action="" enctype="multipart/form-data">
<!-- path gibt den Namen der member Variablen an -->
Input-File (.pdf): <form:input path="file" type="file"/><br />
<input type="submit" value="Start Circle Up">
</form:form>
</body>
And this are the relevant methods of my Controller:
#RequestMapping(value = "/CircleUp", method = RequestMethod.GET)
public String circleUpGet(Model model) {
CircleUpForm circleUpForm = new CircleUpForm();
model.addAttribute("circleUpForm", circleUpForm);
// Eine einzelne .jsp wird returnt
return "CircleUp";
}
// POST: CircleUp
#RequestMapping(value = "/CircleUp", method = RequestMethod.POST)
public String circleUpPost(HttpServletRequest request, Model model, //
#ModelAttribute("circleUpForm") CircleUpForm circleUpForm) {
return this.doUpload(request, model, circleUpForm);
}
This is my Form:
import org.pdfclown.files.File;
public class CircleUpForm {
// private CommonsMultipartFile file;
// File
private File file;
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
}
The GET method works well, but when clicking on the submit button on my view the error appears. Thus I think something went wrong on my POST Method. I tried to debug the problem but not even the method is executed. I have just started programming with Spring MVC and I´m not really familiar with some concepts. Maybe someone has an idea? Thank you !
Remove the "enctype="multipart/form-data" tag from your .jsp.

Spring controller get empty object

I'm sending an object to spring controller via jsp form.
JSP:
<form:form modelAttribute="uploadItem" action="/uploadObject" method="post" enctype="multipart/form-data">
<form:input path="fileData" accept="audio/mpeg" type="file" id="file-upload" name="file-upload" />
<form:input type="text" path="title" id="upload-title" name="upload-title"/>
<input type="image" src="..." alt="Upload"/>
</form:form>
ModelService:
public void fillUploadMelodyModel(Model model) {
fillAdminRootModel(model);
model.addAttribute("uploadItem", new UploadedItem());
}
UploadedItem:
public class UploadedItem {
private CommonsMultipartFile fileData;
private String title;
}
Controller:
#RequestMapping(value = "/uploadObject", method = RequestMethod.POST)
public String doUpload(UploadedItem uploadItem, BindingResult result, Principal principal) {
//at this point I get an empty object (null null values)
}
What is the problem? How to pass object to controller in jsp?
Try changing then your controller like this
#RequestMapping(value = "/uploadObject", method = RequestMethod.POST)
public String doUpload(UploadedItem uploadItem,
BindingResult result,
#RequestParam("fileData") MultipartFile file,
#RequestParam("title") String title,
Principal principal) {
//Here you should receive your parameters
}
I think the names you have used for the file (file-upload) and title (upload-title) are not in sync with your domain object attribute names. Change your names to fileData and title in your Jsp page.

File upload working under Jetty but not under Tomcat

I have a web application with spring in which I do some file upload. Under eclipse, using Jetty (the maven plugin) it works perfectly. But when I deploy the application under Tomcat it does not and I get the following Exception :
org.springframework.web.bind.MissingServletRequestParameterException: Required org.springframework.web.multipart.MultipartFile parameter 'file' is not present
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.raiseMissingParameterException(AnnotationMethodHandlerAdapter.java:545)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveRequestParam(HandlerMethodInvoker.java:336)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:207)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:132)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:326)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:313)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
Here is my form :
<form method="post" action="../admin/import.html" id="import"
enctype="multipart/form-data">
<div id="importInmates" align="center">
<input type="file" name="file" id="file"
data-dojo-type="dijit.form.Button"
label="<fmt:message key='import.file' />" />
<button data-dojo-type="dijit.form.Button" id="importInmates"
type="submit">
<fmt:message key="import.import" />
</button>
</div>
<input type="hidden" name="importType" value="inmates" />
</form>
And here is the intercepting method :
#RequestMapping(value = IMPORT_PAGE, method = RequestMethod.POST)
public String recieveFile(#RequestParam("importType") String importType,
#RequestParam("file") MultipartFile multipartFile, final HttpSession session)
{
if (multipartFile.getSize() < 0)
{
LOGGER.debug("No file has been uploaded");
return "redirect:.." + IMPORT_PAGE;
}
File file = new File("tmp");
try
{
multipartFile.transferTo(file);
BufferedReader lec = new BufferedReader(new FileReader(file));
LOGGER.debug(lec.readLine());
lec.close();
}
catch (Exception e)
{
LOGGER.error("An exception occured while reading " + importType + " file", e);
}
return "redirect:.." + IMPORT_PAGE;
}
I have added the following bean :
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000000"></property>
</bean>
both in applicationContext.xml and mvc-servlet.xml even if I think that only the latter is important.
Any help would be appreciated.
Thanks.
Thanks to #Bart I was able to find the following simple solution :
In the intercepting method, use #ModelAttribute instead of #RequestParam :
#RequestMapping(value = IMPORT_PAGE, method = RequestMethod.POST)
public String recieveFile(#RequestParam("importType") String importType,
#ModelAttribute("file") UploadedFile uploadedFile, final HttpSession session)
{
MultipartFile multipartFile = uploadedFile.getFile();
Where UploadedFile is the following class :
public class UploadedFile
{
private String type;
private MultipartFile file;
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
public void setFile(MultipartFile file)
{
this.file = file;
}
public MultipartFile getFile()
{
return file;
}
}
And it's working !!
Thanks everyone for your help.
Use #RequestPart instead of #RequestParam.
From the source:
Annotation that can be used to associate the part of a "multipart/form-data" request
with a method argument. Supported method argument types include {#link MultipartFile}
in conjunction with Spring's {#link MultipartResolver} abstraction,
{#code javax.servlet.http.Part} in conjunction with Servlet 3.0 multipart requests,
or otherwise for any other method argument, the content of the part is passed through an
{#link HttpMessageConverter} taking into consideration the 'Content-Type' header
of the request part. This is analogous to what #{#link RequestBody} does to resolve
an argument based on the content of a non-multipart regular request.
Note that #{#link RequestParam} annotation can also be used to associate the
part of a "multipart/form-data" request with a method argument supporting the same
method argument types. The main difference is that when the method argument is not a
String, #{#link RequestParam} relies on type conversion via a registered
{#link Converter} or {#link PropertyEditor} while #{#link RequestPart} relies
on {#link HttpMessageConverter}s taking into consideration the 'Content-Type' header
of the request part. #{#link RequestParam} is likely to be used with name-value form
fields while #{#link RequestPart} is likely to be used with parts containing more
complex content (e.g. JSON, XML).

how to get param in method post spring mvc?

I'm using spring mvc. And I can't get param from url when method = post. But when I change method to GET, so I can get all param.
This is my form:
<form method="POST" action="http://localhost:8080/cms/customer/create_customer" id="frmRegister" name ="frmRegister" enctype="multipart/form-data">
<input class ="iptRegister" type="text" id="txtEmail" name="txtEmail" value="" />
<input class ="iptRegister" type="password" id="txtPassword" name="txtPassword" value="" />
<input class ="iptRegister" type="text" id="txtPhone" name="txtPhone" value="" />
<input type="button" id="btnRegister" name="btnRegister" value="Register" onclick="" style="cursor:pointer"/>
</form>
This is my controller:
#RequestMapping(value= "/create_customer", method = RequestMethod.POST)
#ResponseBody
public String createCustomer(HttpServletRequest request,
#RequestParam(value="txtEmail", required=false) String email,
#RequestParam(value="txtPassword", required=false) String password,
#RequestParam(value="txtPhone", required=false) String phone){
ResultDTO<String> rs = new ResultDTO<String>();
rs.setStatus(IConfig.SHOW_RESULT_SUCCESS_ON_MAIN_SCREEN);
try{
Customer c = new Customer();
c.setEmail(email);
c.setPassword(password);
c.setPhone(phone);
customerService.insert(c);
rs.setData("Insert success");
}catch(Exception ex){
log.error(ex);
rs.setStatus(IConfig.SHOW_RESULT_ERROR_ON_MAIN_SCREEN);
rs.setData("Insert failure");
}
return rs.toString();
}
How can I resolved this?
Spring annotations will work fine if you remove enctype="multipart/form-data".
#RequestParam(value="txtEmail", required=false)
You can even get the parameters from the request object .
request.getParameter(paramName);
Use a form in case the number of attributes are large. It will be convenient. Tutorial to get you started.
Configure the Multi-part resolver if you want to receive enctype="multipart/form-data".
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="250000"/>
</bean>
Refer the Spring documentation.
It also works if you change the content type
<form method="POST"
action="http://localhost:8080/cms/customer/create_customer"
id="frmRegister" name="frmRegister"
enctype="application/x-www-form-urlencoded">
In the controller also add the header value as follows:
#RequestMapping(value = "/create_customer", method = RequestMethod.POST, headers = "Content-Type=application/x-www-form-urlencoded")
When I want to get all the POST params I am using the code below,
#RequestMapping(value = "/", method = RequestMethod.POST)
public ViewForResponseClass update(#RequestBody AClass anObject) {
// Source..
}
I am using the #RequestBody annotation for post/put/delete http requests instead of the #RequestParam which reads the GET parameters.
You should use #RequestParam on those resources with method = RequestMethod.GET
In order to post parameters, you must send them as the request body. A body like JSON or another data representation would depending on your implementation (I mean, consume and produce MediaType).
Typically, multipart/form-data is used to upload files.

spring 3 auto form field validation with file upload

I was using JSR 303 validation with hibernate validator to have fields validated automatically by specifying #Valid on the controller method. Validation was working fine. I have know added an upload field to the form and have added a #RequestParam("file") as a MultipartFile file. Now it works only if all fields are valid on submission otherwise I get a 404 (Bad Request). If I remove the #Valid annotation I get the javax.validation.ConstraintViolationException with all the validation violations with Status 500.
I'm using Spring 3.2
my form:
<form action="#springUrl("/admin/stores/save")" method="POST" enctype="multipart/form-data">
Name:
#springBind( "store.name" )
<input type="text"
name="${status.expression}"
value="$!status.value" /><br>
......
<input type="file" name="file" accept="image/*">
<input type="submit" value="submit"/>
</form>
Controller:
#RequestMapping(value="/save", method = RequestMethod.POST)
#Transactional
public String save(#Valid #ModelAttribute Store store, #RequestParam("file") MultipartFile file, BindingResult bindingResult, ModelMap model) {
if (bindingResult.hasErrors()) {
model.addAttribute("message", "Failed");
model.addAttribute("store", store);
return "admin/stores/form";
} else {
.....
your problem is in method argument order. #ModelAttribute must be followed by BindingResult argument. Look at Spring documentation and check also Example 17.1. Invalid ordering of BindingResult and #ModelAttribute.
. You also should add MultipartFile to form class (Store) if it is part of it.
Store {
/* Your other fields */
#NotNull
private MultipartFile file;
public MultipartFile getFile() {
return file;
}
public void setFile(MultipartFile file) {
this.file= file;
}
}

Categories