I'm trying to upload an image following this and this tutorial but without using maven.
Here is my config related to upload:
ApplicationContext.xml
..
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10000000">
</property></bean>
My form:
<form:form
action="${ contextPath }admin/add-product"
method="POST" modelAttribute="addInventoryItemDto"
enctype="multipart/form-data">
<table>
....
<tr>
<td><b>Image:</b></td>
<td><input type="file" name="image" /></td>
</tr>
....
Controller
#RequestMapping( value = "/add-product", method = RequestMethod.POST )
public String addProduct(
#ModelAttribute( "addInventoryItemDto" ) #Valid AddInventoryItemDto inventoryDto,
#RequestParam( "image" ) MultipartFile img ) {
System.out.println("ContentType:" + img.getContentType());
return "admin/add-product";
}
I'm getting 404 Bad Request but when I remove the file related stuff in my Controller and form the request is properly sent to my controller
What I'm I missing or did wrong?
Try adding this tag:
<spring:url value="/add-product?${_csrf.parameterName}=${_csrf.token}" var="addItem"/>
And put this to the action attribute:
<form:form
action= "${addItem}"
method="POST" modelAttribute="addInventoryItemDto"
enctype="multipart/form-data" >
<table>
....
<tr>
<td><b>Image:</b></td>
<td><input type="file" name="image" /></td>
</tr>
....
If this isn’t working try also add the MultiPartHttpServletRequest object to your controller:
#RequestMapping( value = "/add-product", method = RequestMethod.POST )
public String addProduct(
#ModelAttribute( "addInventoryItemDto" ) #Valid AddInventoryItemDto inventoryDto,
MultiPartHttpServletRequest request,
#RequestParam( "image" ) MultipartFile img ) {
System.out.println("ContentType:" + img.getContentType());
return "admin/add-product";
}
I just moved the multipartResolver
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10000000">
</property></bean>
to my servlet-dispatcher configuration. Seems like that multipartResolver is part of spring MVC not the spring core
Related
while fetching file from spring form I am getting null value and If I try this code for rest of fields i mean non multipart input types its working fine. while debugging I am getting null value from line. If I try to fetch image from existing folder i'e image under webapp and that url is able to display image in browser but not able to read value from files using browser and sorry for my bad english
edit if i comment the image code, application is working fine but when I introduce the code for image I'm getting error
MultipartFile file = domain.getImage(); //this is getting null
this is relevent code
controller
#RequestMapping(value = "/form", method = RequestMethod.GET)
public String formInputGet(Model model) {
model.addAttribute("domain", new Domain());
return "form";
}
#RequestMapping(value = "/form", method = RequestMethod.POST)
public String formInputPost(#ModelAttribute("domain") Domain domain, HttpServletRequest httpServletRequest) {
MultipartFile file = domain.getImage();
if (image== null)
throw new NullPointerException("unable to fetch "+file); //getting NPE everytime
String rootDirectory = httpServletRequest.getSession().getServletContext().getRealPath("/");
if (domain.getImage() != null && !domain.getImage().isEmpty())
try {
File path = new File(rootDirectory + "images\\" + domain.getFirstName() + ".png");
file.transferTo(path);
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
}
repositiry.addToList(domain);
return "redirect:/";
}
form.jsp
<form:form modelAttribute="domain" enctype="multipart/form-data">
First Name<br>
<form:input path="firstName" />
<br>Last Name :<br>
<form:input path="lastName" />
<br>upload Image<br>
<form:input path="image" type="file" />
<hr>
<input type="submit">
</form:form>
dispatcherServlet
<mvc:annotation-driven />
<mvc:resources location="/images/" mapping="/images/**" />
<context:component-scan base-package="com" />
<bean id="multipartReslover"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10240000" />
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/" />
<property name="suffix" value=".jsp" />
</bean>
I added some extra code to find if I am getting domain as null came to be true. And I have no Idea how to solve that.
after adding check for file i'm getting error
java.lang.NullPointerException: unable to fetch : null
domain.java
public class Domain {
private String firstName;
private String lastName;
private MultipartFile image;
//getters and setters
NOTE any helpful answer if it have other way of working is welcomed too :)
any help is appreciated, thanks :)
you should do everything #kuhajeyen said and if getting image from domain object didnt go well you can try this
public String formInputPost(#ModelAttribute("domain") Domain domain,
#RequestParam("image") MultipartFile imagefile,
HttpServletRequest httpServletRequest ) {
imagefile.transferTo(path);
}
edit :- change method attribute to POST inside the form otherwise it will make a GET request.
<form:form modelAttribute="domain" method="post" enctype="multipart/form-data">
and replace your input type file with this line, i think there is some issues when trying to bind input type file with an object.
<input type="file" name="image" />
You need to tell the spring, how to resolve multipart file
add this bean
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="409600"/>
</bean>
And also it seems you have not mapped your action in form
<form:form modelAttribute="domain" enctype="multipart/form-data" action="xxxx/form">
....
</form:form>
There were two typos in my configuration file as they are
1) <mvc:resources location="/images/" mapping="/images/**" /> here mapping was supposed to be like mapping ="images/**"
2)File path = new File(rootDirectory + "images\\" + domain.getFirstName() + ".png"); here path is supposed to be as rootDirectory+"\\images\\"+.... instead
#RequestMapping(value = "{fileName:.+}", method = RequestMethod.POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE})
public ResponseEntity<ResponseEnvelope<String>> uploadFile(
#RequestParam("ownerId") Long ownerId,
#PathVariable("fileName") String fileName,
#RequestBody MultipartFile file)
throws Exception {
ResponseEnvelope<String> env;
if(null == certFileContent) {
env = new ResponseEnvelope<String>("fail");
return new ResponseEntity<ResponseEnvelope<String>>(env, HttpStatus.OK);
}
service.uploadCertificate(ownerId, fileName, certFileContent.getBytes());
env = new ResponseEnvelope<String>("success");
return new ResponseEntity<ResponseEnvelope<String>>(env, HttpStatus.OK);
}
Why I always get the file value is null, I've configure the multipart support,see below,
The file should be binded to a RequestParam instead of the RequestBody as follows:
public ResponseEntity<ResponseEnvelope<String>> uploadFile(
#RequestParam("ownerId") Long ownerId,
#PathVariable("fileName") String fileName,
#RequestParam(value = "file") MultipartFile file)
This would correspond with the following HTML form:
<form method="post" action="some action" enctype="multipart/form-data">
<input type="file" name="file" size="35"/>
</form>
Then in your dispatcher configuration specify the CommonsMultiPartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="5000000"/>
</bean>
This is what worked for me,
Previously my input field was defined as,
<input type="file" />
I was getting null file with the above line but when I added the name="file" everything worked fine!
<input type="file" name="file" />
Hope this helps!
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.
I am getting the below error while uploading the files (multiple files) using Spring MVC.
java.lang.NullPointerException
com.mkyong.common.controller.FileUploadController.save(FileUploadController.java:34)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
jsp
<form:form method="post" action="save"
modelAttribute="uploadForm" enctype="multipart/form-data">
<p>Select files to upload. Press Add button to add more file inputs.</p>
<input id="addFile" type="button" value="Add File" />
<table id="fileTable">
<tr>
<td><input name="files[0]" type="file" /></td>
</tr>
<tr>
<td><input name="files[1]" type="file" /></td>
</tr>
</table>
<br/><input type="submit" value="Upload" />
</form:form>
Controller
#RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(
#ModelAttribute("uploadForm") FileUploadForm uploadForm,
Model map) {
List<MultipartFile> files = uploadForm.getFiles();
List<String> fileNames = new ArrayList<String>();
//counting the file size
System.out.println("Files count :"+files.size());
if(null != files && files.size() > 0) { //HERE 'files' is NULL
for (MultipartFile multipartFile : files) {
String fileName = multipartFile.getOriginalFilename();
fileNames.add(fileName);
//Handle file content - multipartFile.getInputStream()
}
}
Can anyone please help me in fixing this? I am still debugging why I am not able to pass the files(uploadForm) from jsp to controller.
I just solved it. you need to add <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" /> in your dispatcher-servlet.xml.
and if you are using multipart array for multiple files then use just array name. like
private MultipartFile [] file;
Getters and Setters and in form
<form:form commandName="uploadFile" method="post" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="file" name="file"/>
<input type="file" name="file"/>
<input type="submit" value="Submit"/>
</form:form>
I need help. I am working on a project where I have multiple pages and multiple forms; each page has one form. I just need to be able to pass values from one jsp to another. What should I do?
I am new to Spring MVC. I am using spring 2.5.6.
Here's my design:
formPage1.jsp --> Controller1 --> formPage2a.jsp --> Controller2 needs val frm pg1 & pg2a.
formPage1.jsp --> Controller1 --> formPage2b.jsp --> Controller3 needs val frm pg1 & pg2b.
formPage1.jsp --> Controller1 --> formPage2c.jsp --> Controller4 needs val frm pg1 & pg2c.
As you can see above, formPage1.jsp can load either formPage2a, formPage2b or formPage2c. Based on the input provided in formPage1.jsp, it goes to the controller (which is an extension of SimpleFormController) and controller get the values entered by user = command object.
I want to be able to use these command object values in either formPage2a, formPage2b or formPage2c when they are submitted to another controller.
here's the current code:
formPage1.jsp:
<form:form method="post" commandName="gainLossRequest">
<form:errors path="*" cssClass="error"/>
<table>
<tr>
<td>
<table>
<tr>
<td><h4>Choose Client</h4></td>
<td style="font-size: medium; font-family: Arial, bold; color: red">*</td>
</tr>
</table>
</td>
<td>
<form:select path="client">
<form:option value="none" label="Select" />
<form:option value="abc" label="abc" />
<form:option value="def" label="def" />
<form:option value="xyz" label="xyz" />
</form:select>
</td>
</tr>
<tr>
<td colspan="2">
<input type="reset" value="Reset" />
<input type="submit" value="Next" />
</td>
</tr>
</table>
</form:form>
Controller1.java
public class TestController extends SimpleFormController {
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
public TestController() {
logger.info("entering TestController.constructor..");
setCommandClass(UserPreference.class);
setCommandName("userPreference");
}
public ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws ServletException {
logger.info("entering TestController.onSubmit all..");
UserPreference userPreference = (UserPreference) command;
ModelAndView view = null;
if ("abc".equals(userPreference.getClient())) {
GainLossRequest gainLossRequest = new GainLossRequest(userPreference);
view = new ModelAndView("redirect:/test/gainLossRequest.htm",
"gainLossRequest", gainLossRequest);
} else if ("def".equals(userPreference.getClient())) {
IncomingPositionsRequest incomingPositionsRequest = new IncomingPositionsRequest();
view = new ModelAndView(
"redirect:/test/incomingPositionsRequest.htm",
"incomingPositionsRequest", incomingPositionsRequest);
} else if ("xyz".equals(userPreference
.getClient())) {
TaxStrategyRequest taxStrategyRequest = new TaxStrategyRequest();
view = new ModelAndView("redirect:/test/taxStrategyRequest.htm",
"taxStrategyRequest", taxStrategyRequest);
}
}
}
formPage2a.jsp
<form:form method="post" commandName="gainLossRequest">
<form:errors path="*" cssClass="error"/>
<table style="width: 60%">
<tr>
<td>Account Number (s):</td>
<td style="font-size: medium; font-family: Arial, bold; color: red">*</td>
</tr>
<tr>
<td>
User Chosen Client:
</td>
<td>
<c:out value="${gainLossRequest.client}"/>
</td>
</tr>
<tr colspan="2">
<td>
<input type="reset" value="Reset" />
<input type="submit" value="Submit" />
</td>
</tr>
dispatcher servlet config
<!-- setupNew.jsp is the first jsp -->
<bean name="/test/setupNew.htm" class="chimeraweb.web.TestController">
<property name="sessionForm" value="true"/>
<property name="commandName" value="userPreference"/>
<property name="commandClass" value="chimeraweb.service.UserPreference"/>
<property name="validator">
<bean class="chimeraweb.service.UserPreferenceValidator"/>
</property>
<property name="formView" value="/test/setupNew"/>
</bean>
<!-- gainLossRequest.jsp is the 2nd jsp where I want to display the values captured in the first jsp page -->
<bean name="/test/gainLossRequest.htm" class="chimeraweb.web.SimpleGainLossController">
<property name="sessionForm" value="true"/>
<property name="commandName" value="gainLossRequest"/>
<property name="commandClass" value="chimeraweb.service.GainLossRequest"/>
<property name="validator">
<bean class="chimeraweb.service.GainLossValidator"/>
</property>
<property name="formView" value="/test/gainLossRequest"/>
</bean>
Please help!!
You could also use session attributes, either manually, such as:
public ModelAndView handleRequest(HttpServletRequest request){
request.getSession().getAttribute("nameOfAttribute");
}
Apologies for writing this as an annotated controller, I do not recall if xml config controllers offer this feature...
There is no Spring code involved for that. The other option is to use the #SessionAttribute annotation on your controller:
#Controller
#SessionAttributes("nameOfAttribute")
public class MyController{
//your session attribute can be accessed in controller methods using #ModelAttribute
public ModelAndView handleRequest(#ModelAttribute("nameOfAttribute")){
session.getAttribute("nameOfAttribute");
}
Note
You will need to clear the session attribute when you are done with it:
request.getSession().setAttribute("nameOfAttribute", null);
You have to persist the user entered information on the first page either using a hidden variable as mentioned above by JB Nizet. Or you can set the value in the model attribute that will be returned on your corresponding controllers.
The pseudo code for you.
formPage1.jsp --> Controller1 --> set the values in this form by retrieving it from the Request object --> formPage2a.jsp --> Controller2 will have val frm both pg1 & pg2a.
In this way there is no need to maintain a session attribute.
The simplest way is to use hidden fields in the second page(s) to store what the user has enetered in the first form. This way, all the fields, inclusing those from the first page, will be submitted with the second form(s).