Spring mvc multipart file upload - spring-mvc

I've seen a lot of answers on stackoverflow about multipart file upload problem in Spring MVC application.
Step by step I've make sure that I don't repeat errors others did.
Here is my form
<form class="form-horizontal" data-toggle="validator"
id="track_existing_repair"
method="post"
action="/euo/testUpload.htm"
enctype="multipart/form-data">
...
<div class="form-group required">
<label class="control-label col-sm-4" for="proofOfPurchaseInput">Select File:</label>
<div class="col-sm-8">
<input name="proofOfPurchase"
id="proofOfPurchaseInput"
type="file"
required/>
</div>
</div>
...
</form>
In pom file I have dependency
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
declared multipartResolver in app-servlet.xml
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- max upload size in bytes -->
<property name="maxUploadSize" value="20971520" /> <!-- 20MB -->
<!-- max size of file in memory (in bytes) -->
<property name="maxInMemorySize" value="1048576" /> <!-- 1MB -->
</bean>
Method mapped to request in Controller class
#RequestMapping(value = {"/testUpload"},headers = "Content-Type=multipart/form-data", method = RequestMethod.POST)
public String testUpload(
#RequestPart(value = "proofOfPurchase", required = false) MultipartFile proofOfPurchaseFile
,HttpServletRequest request
) throws InvalidFormatException, IOException {
if(proofOfPurchaseFile != null){
readFile(proofOfPurchaseFile);
}
return NAV_HOME;
}
I tried #RequestParam instead #RequestPart
Without required = false I have "Required request part
'proofOfPurchase' is not present" response, so I made it not required
only to get in to examine request in debugger
So when I stop in debugger I wasn't surprised that request object shows me that file was received and even stored in jBoss temporary folder.
Could you please point out what I could miss that Spring can't see uploaded file?

The problem appears in legacy project where we also use Struts.
It's turn out that struts dispatcher somehow conflicts with spring CommonsMultipartResolver.
Once I've removed all struts servlets and filters from web.xml everything start working.

Related

No mapping found for HTTP request with URI - No dispatcherservlet / servletmapping error

I know this is a common question but I'm getting desesperated here, Im pretty newbie and have been stuck with this for a long time now... I know this is not a DispatcherServlet or Servlet Mapping error as I'm working on a really big project that has everything working already.
What I need to do is add a form on an already existing jsp page, here is what I have
CONTROLLER:
#Controller
#RequestMapping("/messaging")
public class MessagingController {
#GetMapping
public String messagingView(Principal principal, Model model) throws ServiceException {
model.addAttribute("messagingInformation", new MessagingInformation());
return foo; -> this returns me to the main jsp where I'm creating the form
}
#PostMapping(value = "/submitInformation") -> I've also tried with #RequestMapping(value = "/submitInformation", method = RequestMethod.POST)
public String submitInformation(#ModelAttribute(value = "messagingInformation") #Valid MessagingInformation messagingInformation) {
return "redirect:/messaging"; -> shouldn't this redirect me to the main jsp?
}
}
JSP:
<form:form action="messaging/submitInformation" modelAttribute="messagingInformation" method="POST">
<div class="row col-sm-12 margin-top-container">
<div class="col-sm-4">
<span class="titles-select-box uppercase-text">RECEIVER</span>
<input name="receiver" type="email" id="receiverId" name="receiverName"
placeholder="Receiver" multiple>
</div>
</div>
<div class="col-sm-12 no-padding-left">
<div class="button-container pull-right">
<input type="submit" value="Send" class="btn btn-default"
id="sendButton" />
</div>
</div>
</form:form>
I'm mainly getting --No mapping found for HTTP request with URI [/foo/messaging/submitInformation] in DispatcherServlet -- I've asked around and I shouldn't add nothing to any cofiguration file or anything, clearly it's something wrong on my side but I can't see it
Leaving this in case anyone finds out... I was requiered to do a manual build so the java changes would show up. This is done through Projects -> Build All

Required CommonMultipartFile parameter 'testFile' is not present in spring mvc

when I upload a file to springmvc, getting a error message "Required CommonsMultipartFile parameter 'textFile' is not present", I don't know why I can meet it, that's my code.
<form id="form" enctype="multipart/form-data">
<input type="text" id="username" name="username" />
<input type="file" id="file" name="textFile" />
<input type="button" onclick="test()" value="上传" />
</form>
<script type="text/javascript">
function test(){
var form = new FormData(document.getElementById("form"));
$.ajax({
url:"http://localhost:8080/giraffe/upload1",
type:"post",
data:form,
cache: false,
processData: false,
contentType: false,
success:function(data){
alert("success!");
}
});
}
That's my controller and configuration.
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<property name="maxUploadSize" value="10240000"/>
</bean>
#RequestMapping(path = "/upload1", method = RequestMethod.POST)
public Object updloadImage(#RequestParam("textFile") CommonsMultipartFile file){
String fileName = file.getOriginalFilename();
return null;
}
Maybe you should change your RequestParam to
#RequestParam MultipartFile textFile
This is of type "org.springframework.web.multipart.MultipartFile"
Also important is that you expose the commons library to your server. So you must add your commons-fileupload-x.x.x.jar to the WEB-INF/lib folder.
And your controller must add the path
#RequestMapping(value="/giraffe")
because your AJAX-Request points to /giraffe/upload1
To check what and if anything is presented to the controller you can add
#RequestParam (required=false) ...
If you have an jsp-File for the page and no plain html then you can use the jstl. This can help you avoid problems with the correct url in your AJAX-request. Like this
url: "<c:url value='/giraffe/upload1' />",

Avoid ajax file upload attack

I have a form and in a HTML form inside which I have file upload button.
File is going to be uploaded using AJAX request.
On file upload I am checking extension and file size.
I am uploading file into /home/xyz/upload/username/username_timestamp
But since I am using AJAX request, I cannot(and don't want to) use the CAPTCHA and there is a risk of attacker flooding with files. How can I deal with this issue?
PS: I am using Spring-MVC(not spring security) and Struts2 in my projects, so framework specific solution will be icing on a cake.
Protect your action to be called out of expected by using Strut's token mechanism and your expected logic of file uploads inside your parent action (e.g. max uploads per minutes) ; something like below:
index.jsp
<form action="upload" method="post" enctype="multipart/form-data">
<label for="myFile">Upload your file</label>
<input type="file" name="myFile" />
<s:if test="uploadsPerMinutes < 10">
<s:token name="tknUpload" /> <!-- *** conditional generate token *** -->
</s:if>
<sj:submit value="Submit Form" targets="myAjaxTarget"/>
</form>
<div id="myAjaxTarget">
</div>
struts.xml
<action name="upload" class="com.upload.FileUpload">
<interceptor-ref name="tokenSession/>
<interceptor-ref name="basicStack"/>
<result name="success" type="stream">...</result>
</action>
<action name="uploadParent" class="com.upload.FileUploadParent">
<result name="success">index.jsp</result>
</action>
FileUploadParent.java
public class FileUploadParent extends ActionSupport{
...
public static int uploadsPerMinutes = 0;
private static DateTime lastUploadTime;
public String execute()
{
...
synchronized(uploadsPerMinutes){
if(currentTime - lastUploadTime > 1min) uploadsPerMinutes=0;
else uploadsPerMinutes++;
lastUploadTime = currentTime;
}
return SUCCESS;
}
public String getUploadsPerMinutes()
{
return uploadsPerMinutes;
}
}
With these, client have to get a token from server for each file upload. These are behind the scene and do not disturb your normal users.

HDIV INVALID_PARAMETER_NAME error with Spring Tag form

I am using a Spring Tag form element in which there are 3 parameters.
<sf:form class="form-horizontal" method="post" name="doCheck" id="checkForm" action="${url}" htmlEscape="true">
<div class="col-sm-12">
<label>Email : <span class="redStar">*</span></label>
<input type="email" name="email" class="form-control user inputIconPos" id="inputEmail3"
placeholder="Email Address"/>
</div>
</div>
//2 more fields
</sf:form>
I am using Spring MVC version 4.1.7 and HDIV version 2.1.11. And the error logged is
21:08:40.386 [http-bio-8100-exec-4] INFO org.hdiv.logs.Logger - INVALID_PARAMETER_NAME;/check_submit.html;email;null;;0:0:0:0:0:0:0:1;0:0:0:0:0:0:0:1;anonymous;
21:08:40.386 [http-bio-8100-exec-4] DEBUG o.hdiv.filter.ValidatorHelperRequest - Validation Error Detected: Parameter [email] does not exist in the state for action [/check_submit.html]
HDIV Config
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:hdiv="http://www.hdiv.org/schema/hdiv"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.hdiv.org/schema/hdiv http://www.hdiv.org/schema/hdiv/hdiv.xsd">
<hdiv:config excludedExtensions="css,png,gif,jpg,jpeg,bmp,ico,js" strategy="cipher" randomName="true" errorPage="/error.html" reuseExistingPageInAjaxRequest="true">
<hdiv:sessionExpired loginPage="/login.html" homePage="/home.html"/>
<hdiv:startPages>/adminlogin.html,/home.html</hdiv:startPages>
</hdiv:config>
<hdiv:validation id="safeText">
<hdiv:acceptedPattern><![CDATA[^[a-zA-Z0-9#.\-_]*$]]> </hdiv:acceptedPattern>
</hdiv:validation>
<hdiv:editableValidations registerDefaults="true">
<hdiv:validationRule url=".*" enableDefaults="true">safeText</hdiv:validationRule>
</hdiv:editableValidations>
</beans>
I don't want to exclude these parameters from validation.
I would like to know how can configure HDIV so that these parameters are validated and not skipped.
Many thanks in advance!
You have to use Spring form tag to create form fields:
<form:input path="email" type="email" ... />
Gotzon
You need to add below configuration in your hdiv config to skip validation on the parameter -
<hdiv:paramsWithoutValidation>
<hdiv:mapping url=".*" parameters="email"/>
</hdiv:paramsWithoutValidation>
In url you can give "/check_submit.html" if you want this on this particular page.

image uploading using spring mvc to jboss server deployment tmp folder

hi my project is based on maven multi module project.
project structure is given below.
im using jboss 7 as my server.
Response
ResponseCommons
ResponseEar
ResponseModel
ResponseService
ResponseWeb
and im done a image upload form. uploading working fine and the image is uploaded to the resource folder of web module.
The problem is the image is uploading to tmp folder of the jboss server ,how can i changes to ResponseWeb/webapp/resources/css/ image name.
current image saving location
C:\jboss-as-7.1.1.Final\stand
alone\tmp\vfs\deploymenteec45ba06bd34543\ResponseWeb-1.2-SNAPSHOT.war-295
28a7e2cc4df5e\resources\css
im using ajax form submit to upload image.
controller for uploading image
#RequestMapping(value = "/uploadImage.html", method = RequestMethod.POST)
#ResponseBody
public String uploadImageTest(#RequestParam("demoImage") MultipartFile file) throws IllegalStateException, IOException {
try {
String fileName = null;
InputStream inputStream = null;
OutputStream outputStream = null;
if (file.getSize() > 0) {
inputStream = file.getInputStream();
System.out.println("File Size:::" + file.getSize());
System.out.println("size::" + file.getSize());
fileName = request.getServletContext().getRealPath("/resources/") + "/css/"
+ file.getOriginalFilename();
outputStream = new FileOutputStream(fileName);
System.out.println("fileName:" + file.getOriginalFilename());
int readBytes = 0;
byte[] buffer = new byte[10000];
while ((readBytes = inputStream.read(buffer, 0, 10000)) != -1) {
outputStream.write(buffer, 0, readBytes);
}
outputStream.close();
inputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return "saved";
}
HTML
<form th:action="#{/school-admin/uploadImage.html}"
id="imageUploadForm" method="post" enctype="multipart/form-data">
<div class="row">
<div class="col-lg-2" style="margin-bottom: -40px;">
<div class="thumbnail">
<img id="imgStud" th:src="#{/resources/img/profile.png}"
style="width: 172px; height: 198px;" /> <br /> <input
type="file" accept="image/*" name="demoImage" id="demoImage"
onchange="fileSelected();" style="width: 170px;" />
</div>
<br />
</div>
</div>
<input type="button" class="btn btn-info pull-right"
id="btnUpload" value="upload" />
</form>
The location you want to save the file is invalid, as it is in fact, inside your WAR file, which gets exploded into the JBoss temp directory, hence you see the .../tmp/vfs/deployment.... folder.
However, you can specify a particular location for your default multi-part upload location, in multiple ways.
If you are using Servlet 3.0, you configure multipart servlet, either as annotation or in web.xml. You can annotate a pure servlet, in the following way.
#WebServlet("/myImageFileUploader")
#MultipartConfig(location = "/opt/myImageFileUploadLocation")
public class MyImageFileUploaderServlet extends HttpServlet {
.....}
XML configuration is as below
<servlet>
<servlet-name>MySpringDispatcher1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-servlet.xml</param-value>
</init-param>
<multipart-config>
<location>/opt/myImageFileUploadLocation</location>
<max-file-size>52428800</max-file-size>
<max-request-size>52428800</max-request-size>
<file-size-threshold>0</file-size-threshold>
</multipart-config>
</servlet>
The above XML example can be used directly in your project, if you are using Servlet 3.0. The sample code is configuring the Spring DispatcherServlet, for your convenience. JBoss 7 Web has Servlet 3.0, by default, so I guess it will work.
If your Servlet version is pre 3.0, I mean, older versions, then you can configure commons-fileupload in the spring configuration file, as given below.
<bean id="myImageMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000" />
<property name="uploadTempDir" ref="myImageFileUploadDirResource" />
</bean>
<bean id="myImageFileUploadDirResource" class="org.springframework.core.io.FileSystemResource">
<constructor-arg>
<value>/opt/myImageFileUploadLocation</value>
</constructor-arg>
</bean>
Hope this helps.

Resources