I am trying to upload multiple files using spring 3.1.2 with #Controller and #RequestMapping.
Here's what I did and my configuration.
Html5 form :
<form action="addFileSystemImage.foo" method="post" enctype="multipart/form-data">
<input class='fileInput' type="file" name="files[]" multiple="multiple" />
<input type="text" value="13asdf12eadsf" name="locId"/>
<input type="submit" />
</form>
Controller method :
#RequestMapping(value="/publisher/addFileSystemImage.foo", method=RequestMethod.POST)
public #ResponseBody List<UploadedFile> addFileSystemImage(#RequestParam("files[]") ArrayList<MultipartFile> files, String locId, HttpServletRequest request) {
//do lotsa voodoo rocket science here to process the files
}
my conf :
<mvc:annotation-driven />
<context:component-scan base-package="foo.package"></context:component-scan>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
Submitting the form does get to the addFileSystemImage method. The data for locId argument is here, but the "files" argument is not bound. It is systematically null no matter what combination of argument / field names / argument types I have tried.
The HttpServletRequest argument is a org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest and it holds a multiPartFile attribute which actually holds the file data. Looking at its value in debug gives me
{files[]=[org.springframework.web.multipart.commons.CommonsMultipartFile#16afd7f9, org.springframework.web.multipart.commons.CommonsMultipartFile#728c2811, org.springframework.web.multipart.commons.CommonsMultipartFile#4f9aaed7]}
which means my files[] is indeed here ... but somehow it did not pass the data binding step properly ...
Now ... I know you're gonna tell me I can retrieve the data from the request ... but I'd rather have this working properly ... the Sring way... :) and have my ArrayList of MultipartFile properly populated.
Am I missing something ? Has anyone actually made this work properly ? What can I do to have this ArrayList (or even an regular Array ) populated?
I came accross this solution
Spring MVC with ajax file upload and MultipartFile which does pretty much the same thing as I am but obviously I must be doing something wrong since this solution is not working for me.
Note : I did manage to get it working with single file uploads. But my challenge today is to get multiple files at once.
Any help appreciated.
Thanks in advance.
Although you've already gotten your answer thanks to Alex, I'd just like to elaborate a bit. With Spring binding, form fields are bound to their "name" attributes in the HTML. Since it is impossible to have a form field named files[] (if one declares a variable name with that syntax, its name is files, but it is an array of the declaring type), Spring couldn't match it up - and the behavior in that case is to disregard the data in the request.
Using a type such as MultipartFile, you can use either a List named "files" or an array as the following examples:
private List<MultipartFile> files;
private MultipartFile[] files;
With appropriate getters and setters, you can then access and mutate the file list accordingly.
Have included commons-fileupload dependency?
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3</version>
</dependency>
I tested the fileupload works fine even with ArrayList as the parameter type on the controller handler
Related
So I have a .jsp page which has a form on it, like this (naturally this is a massive simplification):
<form:form commandName="myCommand" method="post">
<form:select path="values" class="select-tall" multiple="multiple" id="mySelect">
<option>first</option>
<option>second</option>
<option>third</option>
</form:select>
<button type="submit" class="button">Save</button>
</form:form>
When the submit button is pressed, the form is submitted(somehow) and the path= attributes are used to bind the data inside the form elements to the properties of an instance of a plain old java object. I understand how this POJO is specified, and I understand how the POST request is routed to the correct controller, but I don't understand where or how the form values are mapped to the given POJO.
What I don't understand is:
How does the spring tag library modify the form such that this binding takes place?
How would one go about doing this in a manual or ad-hoc fashion(using a Javascript onSubmit() method, say)?
Essentially my question is: How does the spring-form.tld tag library work?
Any resources, or even a high-level explanation in your own words, would be extremely helpful.
I've implemented a work-around solution in the mean time (dynamically adding items to a hidden form element), but I feel like this is hack-y and the wrong solution.
I am stucked to something. In spring 2.5 framework, I want to upload file by using MultipartFile. I have a class called Dosya including property which is MultipartFile multiDosya. My command object is dosya. Additonally, The file which will be uploaded is stored BLOB type in database, sql developer,.
In jsp, I try to bind this propert like below:
<spring:bind path="dosya.multiDosya">
<input class="file" type="file" name="yuklenecekDosya" id="yuklenecekDosya" />
</spring:bind>
In onSubmit,
Dosya dosyaObjesi = (Dosya)command;
MultipartFile yuklenecekDosya = dosyaObjesi.getMultiDosya();
The commandObject dosyaObjesi is taken without problem, however,
dosyaObjesi.getMultiDosya()
value is coming null although file that will be uploaded is selected in jsp.
After searching on the net, I found that this line below should be added to the initBinder.
binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
However, my class says that there is no such class ByteArrayMultipartFileEditor, but it is available in spring-2.5.jar. I import
import org.springframework.web.multipart.*;
can trace out the problem . could someone please help me out
Thanks in advance.
Have you specified form encryption type(enctype="multipart/form-data")?. That could be the reason sometimes.
Ex:
<form method="post" name="formName" action="action.htm" commandName="object" enctype="multipart/form-data">
I have solved the problem. Everything is ok, however, in the code below
<input class="file" type="file" name="yuklenecekDosya" id="yuklenecekDosya" />
the attribute name must be ${status.expression} . That is, exactly, name="${status.expression}" like that. If only the name property value is given like that, bind operation works correctly.
Thanks,
Regards,
I am trying to validate 2 model attributes on one action using spring validation framework. The purpose is to validate the lookUpbean (search criterion) on click of Search button and then to validate the resultant bean also i.e memberShipbean once we get it from the services so that we can show warnings to the user if some fields are empty in the resultant bean.
<form:form method="POST" modelAttribute="lookupPageBean" id="lookupForm" name="lookupForm"
action="lookupMembership.htm">
<td class="error">
<form:errors path="membershipNumber" />
<form:input class="medium-textbox" id="membershipNumber" path="membershipNumber" />
<button type="submit" class="Active-button-small">
<fmt:message key="button.go" />
</button>`
#RequestMapping(method = RequestMethod.POST, value = URLMappingConstant.MEMBERSHIP_LOOKUP)
public String viewMembership(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response,
#ModelAttribute(UIConstant.LOOKUP_PAGE_BEAN) LookupPageBean lookupPageBean, BindingResult result,
#ModelAttribute(UIConstant.MEMBERSHIP_BEAN) MembershipPageBean membershipPageBean, BindingResult error) throws WebMTracksException
{
membershipValidator.validate(lookupPageBean, result);
membershipValidator.validate(membershipPageBean, error);
}
Now what is happening is first validation is working fine however during second validation
the error messages are not shown on the resultant jsp ,
however the errors are reported till this controller layer in the “error” binding results.
Also in the validation layer
ValidationUtils.rejectIfEmpty(errors, UIConstant.BUSINESSNAME,ValidationMSGConstants.BUSINESS_NAME)
This method always returns validation errors even if the field is not empty.
First question is can we have multiple model attributes in one action. I read it somewhere on internet but could not find any implementation of the same. Please help me to resolve this issue. Also let me know if you can think of any other working solution for this problem but I would like to use only the spring framework for the both the validations as that helps to maintain the existing design of the application.
I do not think you have bind multiple Model Attributes to the same form, which I believe is what you are asking. I am not even sure what that request would look like, from an HTTP stand point, as I don't believe Spring would have a way to detangle all the bean's properties, especially if the names overlap. What you may want to consider doing is wrapping your LookupPageBean and MembershipPageBean into one "form bean".
As for the error messages, you may want to take a look at the spring:bind tag. It may do what you are needed to get the binding errors from the second Model Attribute.
I am trying to get some data from a Form with jersey and i though it would be an easy task to accomplish, however I am getting an error when I try to POST something.
Caused by: java.lang.IllegalStateException: The #FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded
at org.glassfish.jersey.server.internal.inject.FormParamValueFactoryProvider$FormParamValueFactory.ensureValidRequest(FormParamValueFactoryProvider.java:126)
at org.glassfish.jersey.server.internal.inject.FormParamValueFactoryProvider$FormParamValueFactory.getForm(FormParamValueFactoryProvider.java:111)
at org.glassfish.jersey.server.internal.inject.FormParamValueFactoryProvider$FormParamValueFactory.get(FormParamValueFactoryProvider.java:94)
at org.glassfish.jersey.server.internal.inject.AbstractHttpContextValueFactory.provide(AbstractHttpContextValueFactory.java:65)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:80)
... 36 more
I think this is the relevant part of the stack trace.
Now for the code I am using:
#POST
#Path("/delete")
#Produces("application/json")
public String delete(#FormParam("id")String id){
And I am trying to POST using a test html page like this:
<form action="<path to the server>/delete" method="post">
primary_id: <input type="text" name="primary_id" /><br />
<input type="submit" value="Submit" />
</form>
I've been trying to make it work but no chance. I have tried adding the #Consumes() annotation with multipart-form-data but can't really make it work. I hope someone can give me a hand.
Thank you all for the help. With some code reviewing i found the problem. Even though I don't think anyone else will make this particular mistake I'll post it anyway for future reference.
The problem was that I am not using a standard web server. I've implemented a netty server with Jersey and the problem was in that said implementation. The problem was that i wasn't passing the headers in the HTTP request to Jersey as I should. I was loosing the Content-Type in the middle of the operation, this means that Jersey couldn't identify the message type.
So, for future reference, for anyone having a similar problem while trying to implement a non-standard server using jersey: when you don't pass the media type correctly (there is a method called getMediaType() in the ContentRequest class that is used, among other things, to validate the Content-Type when #FormParam is used) you will get this type of Exception.
Again, thank you all for the help :)
Your code is working fine except you need to change
<input type="text" name="id" />
Since you havent define #Consumes(), by default delete method consumes mediaType="application/x-www-form-urlencoded" .
I have tested your code and it is working perfectly fine here. My suggestion is check your jersey jar files Specially jsersey-server.jar file in your lib folder.
You are naming your input as "primary_id", but you are receiving "id" name in your #FormParm annotation. Change the id and name in your input tag to "id".
Also if you are consuming application/x-www-form-urlencoded, add this attribute to your form tag: enctype="application/x-www-form-urlencoded"
I'm having a problem uploading a file using spring webflow 1.0 and struts 1.3.
The jsp is something like this:
<html:form action="/flowAction" method="post" enctype="multipart/form-data">
<!-- snip -->
<html:file property="file" name="attachDocumentsForm" size="50"/>
<!-- snip -->
</html:form>
The Form is something like this:
public class AttachDocumentsForm extends SpringBindingActionForm {
// note, SpringBindingActionForm extends struts' ActionForm
private FormFile file;
//snip
}
Now, my problem is that when I submit the form, the file field is always null. The other fields on the form are filled out properly, and if I dig through the RequestContext, I can find the file is buried deep some of the data structures there.
Here is the horribly ugly way that I can get at the attachment:
// 'context' is the RequestContext
ServletExternalContext servletExternalContext = (ServletExternalContext) context.getExternalContext();
ActionForm form = (ActionForm) servletExternalContext.getRequest().getAttribute("actionForm");
FormFile file = (FormFile) form.getMultipartRequestHandler().getFileElements().get("file");
I've noticed that the MultipartRequestHandler on my form is null, and I suspect that this might be part of the problem, but I've tried populating it with an instance of CommonsMultipartRequestHandler to no avail.
What do I need to do to let the file field be populated correctly?
I think you should configure spring dispatcher servlet: http://static.springsource.org/spring/docs/2.0.x/reference/mvc.html#mvc-multipart-resolver
Add a field called file of type FormFile in your ActionForm (the one referred by attachDocumentsForm), along with the accessor methods.
The uploaded file can be accessed by calling form.getFile().
I hope this helps!