Required CommonMultipartFile parameter 'testFile' is not present in spring mvc - 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' />",

Related

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.

how to correctly render a response on an gsp from on the same page as the request (REST call) in grails

I am new to grails and groovy.
I am trying to find out how to render a response from an action in a grails controller IN THE SAME gsp - but in a DIFFERENT SECTION OF THE gsp - as the gsp that takes the request (in this case a web form gsp page)?
any links or turorials or just straight to the point "do this" kind of replies are welcomed.
========= background with my code attempt) =========
Here is the code I am working with. It is a Grails application in which I am using a bootstrap template (available for free on the internet of course).
Now the actual code itself for functionality works. What I am having an issue with is this:
I have a gsp page that uses a css template and another gsp temlate for layout (this is from the bootstrap theme). I can start the page with the gsp+css tempate using this code (snippet) in my gsp page:
<g:layoutBody/>
This allows me to call my calling controller code in this gsp file for the request:
<body>
<g:form name="form" controller="apiStart" id="form">
<div><g:select name="protocolType" value="restCall" from="${["-select-", "GET", "POST", "PUT", "DELETE"]}"/> &nbsp <label>URL: </label><g:textField name="url" value="${url}" />
&nbsp <label>username: </label><g:textField name="userName" value="${userName}" /> &nbsp <label>password: </label><g:textField name="passWord" value="${passWord}" /></div>
%{--<div class="text-field"><label>URL: </label><g:textField name="url" value="${url}" /></div>--}%
%{--<div class="text-field"><label>username: </label><g:textField name="userName" value="${userName}" /></div>
<div class="text-field"><label>password: </label><g:textField name="passWord" value="${passWord}" /></div>--}%
<br>
<div><label>Use Advanced Parameters?</label><g:checkBox name="useAdvParms" value="${false}" /></div>
<div class="text-field"><label>Header1: </label><g:textField name="header1" value="${header1}" /> &nbsp <label>Value1: </label><g:textField name="value1" value="${header2}" /></div>
%{--<div class="text-field"><label>Value1: </label><g:textField name="value1" value="${header2}" /></div>--}%
<div class="text-field"><label>Header2: </label><g:textField name="header2" value="${header3}" /> &nbsp <label>Value2: </label><g:textField name="value2" value="${header4}" /></div>
%{--<div class="text-field"><label>Value2: </label><g:textField name="value2" value="${header4}" /></div>--}%
<br>
<div class="submit"><g:actionSubmit value="Submit" action="save"/></div>
</g:form>
</body>
And then this gsp code for the response:
<body>
<h3>API Test Results</h3>
API Tested: ${apiStart.url}, Response: ${apiStart.response3}
<br>
%{--<g:textArea name="myField" value="myValue" rows="20" cols="100"/>--}%
<div class="textarea"><label>Output</label><br><g:textArea name="myField" value="${apiStart.result3}" />
</div>
%{--Responce Code: ${apiStart.response3}<br>--}%
%{--Response: <br> ${apiStart.result3} <br>--}%
</body>
My issueis this: it works fine as separate pages. I want to render the results of the request on the same page as the calling request.
in the screen shot attached: I want to put the results in the text box where it says "Output Displayed here...."
I assumed templates in grails is the way to go about it; but I get a Java Null pointer exception when I try to insert the template into that part of the code.
here is the template gsp code:
<div>
API Tested: ${apiStart.url}, Response: ${apiStart.response3}
<br>
%{--<g:textArea name="myField" value="myValue" rows="20" cols="100"/>--}%
<div class="textarea"><label>Output</label><br><g:textArea name="myField" value="${apiStart.result3}" />
</div>
%{--Responce Code: ${apiStart.response3}<br>--}%
%{--Response: <br> ${apiStart.result3} <br>--}%
</div>
======== UPDATE: Addidng controller code ===========
controller:
package hellograils
import org.springframework.http.HttpMethod
import org.springframework.web.client.RestTemplate
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import java.util.Base64;
import java.util.Map;
import static javax.xml.bind.DatatypeConverter.parseString;
class ApiStartController {
def index() {
}
def save() {
def apiStart = new ApiStart(params)
apiStart.save()
render (view: "apiStart", model: [apiStart: apiStart])
System.out.println(apiStart.url);
System.out.println(apiStart.passWord);
System.out.println(apiStart.userName);
RestTemplate restTemplate = new RestTemplate();
System.out.println ("URI under Test is: " + String.valueOf(apiStart.url) + ". \n" + "Please stand by for results ... \n \n ");
//String linkUT = apiStart.url;
// apiStart.result3 = restTemplate.exchange(apiStart.url, HttpMethod.GET, null, String.class).getBody();
// apiStart.response3 = restTemplate.exchange(apiStart.url, HttpMethod.GET, null, String.class).getStatusCode();
if (apiStart.protocolType == "GET") {
apiStart.result3 = restTemplate.exchange(apiStart.url, HttpMethod.GET, null, String.class).getBody();
apiStart.response3 = restTemplate.exchange(apiStart.url, HttpMethod.GET, null, String.class).getStatusCode();
render(view: "apiStart", model:[apiStart: apiStart])
System.out.println(apiStart.protocolType);
System.out.println(apiStart.result3);
System.out.println(apiStart.response3);
}
else if (apiStart.protocolType == "POST") {
//apiStart.result3 = restTemplate.exchange(apiStart.url, HttpMethod.POST, request, String.class).getBody();
apiStart.result3 = restTemplate.execute(apiStart.url, HttpMethod.POST, null, String.class).getBody();
apiStart.response3 = restTemplate.exchange(apiStart.url, HttpMethod.POST, null, Map.class).getStatusCode();
// apiStart.result3 = restTemplate.exchange(apiStart.url, HttpMethod.POST, null, String.class).getBody();
// apiStart.response3 = restTemplate.exchange(apiStart.url, HttpMethod.POST, null, String.class).getStatusCode();
render(view: "apiStart", model:[apiStart: apiStart])
System.out.println(apiStart.protocolType);
System.out.println(apiStart.result3);
System.out.println(apiStart.response3);
}
else if (apiStart.protocolType == "PUT") {
render(view: "apiStart", "coming soon ....")
System.out.println(apiStart.protocolType);
System.out.println(apiStart.result3);
System.out.println(apiStart.response3);
}
else if (apiStart.protocolType == "DELETE") {
render(view: "apiStart", "coming soon ....")
System.out.println(apiStart.protocolType);
System.out.println(apiStart.result3);
System.out.println(apiStart.response3);
}
}
}
=================== end of controller code ==================
and here is the domain controller code:
================ domain model code ==========================
domain:
package hellograils
class ApiStart {
String url
String userName
String passWord
String result3
String response3
String header1
String header2
String value1
String value2
String protocolType
// static constraints = {
// }
}
======================= end of domain ================
Can someone advise and show me the best way to do this?
thanks.
ironmantis7x
Include the results pane in your gsp, but wrap it with a g:if tag. Supply a flag variable that determines whether grails renders that portion of the output or not.
<g:if test="${apiStart != null}">
<div class="textarea">
<label>Output</label><br>
<g:textArea name="myField" value="${apiStart.result3}" />
</div>
</g:if>
In the edit method, define apiStart as:
def apiStart = params.apiStart
When the edit view is initially rendered, the results pane should not appear.
In the save method, do whatever you're doing, define the apiStart map, populate it, and redirect to the edit method passing the apiStart as a parameter.
redirect(view:'edit', params:[apiStart:apiStart])
Or something like that. Haven't seen your controller code...

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.

Error uploading file from form-data to Spring Server

I am uploading a picture using form-data taking the picture from the Client's PC to Spring MVC Server.
Update Page:
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring MVC - Upload File</title>
</head>
<body>
<form id="form1" method="post" action="/upload" enctype="multipart/form-data" accept-charset="utf-8">
<!-- File input -->
<input name="file" id="file" type="file" /><br/>
<input type="submit" value="Upload" />
</form>
</body>
</html>
And this is the Spring Controller
#RequestMapping(value = "upload", method = RequestMethod.POST)
public #ResponseBody
String provaUpdate(MultipartHttpServletRequest request,Principal p,HttpServletResponse response)throws IOException {
String result="";
LocalFileManager mLocalFileManager = LocalFileManager.get();
Iterator<String> iterator = request.getFileNames();
while(iterator.hasNext())
{
System.out.println("iterator.next()="+iterator.next());
}
System.out.println("request.getFileMap().isEmpty()??"+request.getFileMap().isEmpty());
// mLocalFileManager.saveLocalData(g,g.getPicturesCount(), request.getFile("new").getInputStream());
return result;
}
So, when i run that, it just prints:
request.getFileMap().isEmpty()??true
Then, no Files seems to be uploaded, but if I get the request.getInputStream() I can write a TXT File showing that:
------WebKitFormBoundaryWG8vA5PuTFFxPBqK
Content-Disposition: form-data; name="file"; filename="1.jpg"
Content-Type: image/jpeg
�� JFIF ��ICC_PROFILE 蠠 mntrRGB XYZ ٠ $ acsp �� ӭ )𽞯򕮸B򤊃9
desc D ybXYZ bTRC Ԡ dmdd ࠠ ɧXYZ
h gTRC Ԡ lumi
| meas
//(Symbols) Long ETC, so the picture is sent !!
------WebKitFormBoundaryWG8vA5PuTFFxPBqK--
So, seems that the picture is sent correctly but the MultipartHttpServletRequest is not able to get the File.
Which is my mistake?
I think,you may be missing below entry in your spring configuration xml file.
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- below properties can be configured as per your need -->
<property name="maxUploadSize" value="5000000" />
<property name="maxInMemorySize" value="5000000" />
</bean>
The mistake was that i am working with Thymeleaf, so the form is different.
It is solved changing that:
1- Create a class that contains a MultipartFile, like this:
public class Images {
MultipartFile image;
public MultipartFile getImage() {
return image;
}
public void setImage(MultipartFile image) {
this.image = image;
}
}
2- The correct form code for a Spring Server working with Thymeleaf:
<form id="myform" action="#" th:action="#{/upload}" th:object="${Images}" method="POST" modelAttribute="Images" enctype="multipart/form-data">
<input type="file" th:field="${Images.image}" name="file"/>
<input type="submit" value="Upload"/>
</form>
And finally the correct Controller method:
#RequestMapping(value = "upload", method = RequestMethod.POST)
public String addVocabularyValadate( #ModelAttribute("Images") Images images,BindingResult bindingResult,
Model model) throws IOException
{
System.out.println("inputstream Nombre!"+images.getImage().getOriginalFilename());
if(bindingResult.hasFieldErrors() == true)
return "error";
else
return "upload OK!";
}

Which Signature to use in spring's controller methods

There are lots of possible signature while defining Spring's Controller method. I'm confused which one should i use and in which circumstances.
For example, I have below scenario.
I have to upload a file to server i have written a form for that
Below is HTML
<form action="uploadimage?id=${pencil.id}" method="post">
<table border="0">
<tr>
<td style="color:maroon;font-weight:bold;">Change/Upload Image</td>
<td><input type="file" name="image" /></td>
<td><input type="submit" value="upload" /></td>
<td><input type="hidden" name="pencilid" value="${pencil.id}" /></td>
</tr>
</table>
</form>
For this I'm writing controller method. While using #ModelAttribute it throws exception saying can't instantiate bean MaltipartFile as its an Interface and while using #RequestParam it returns 400 error code
using #requestParam
#RequestMapping(value="/uploadimage",method=RequestMethod.POST)
public ModelAndView uploadImage(#RequestParam ("pencilid") String id,#RequestParam("file") MultipartFile file)
{
System.out.println("In Controller");
Pencil pencil=null;
PencilService pencilService=ServiceFactory.getPencilService();
pencil=pencilService.getPencil(Integer.parseInt(id));
ModelAndView model= new ModelAndView("pencilview","pencil",pencil);
model.addObject("id",id);
//MultipartFile file=(MultipartFile)param.get("image");
System.out.println(file.getName());
return model;
}
Using #ModelAttribute
#RequestMapping(value="/uploadimage",method=RequestMethod.POST)
public ModelAndView uploadImage(#ModelAttribute ("pencilid") String id,#ModelAttribute("file") MultipartFile file)
{
System.out.println("In Controller");
Pencil pencil=null;
PencilService pencilService=ServiceFactory.getPencilService();
pencil=pencilService.getPencil(Integer.parseInt(id));
ModelAndView model= new ModelAndView("pencilview","pencil",pencil);
model.addObject("id",id);
//MultipartFile file=(MultipartFile)param.get("image");
System.out.println(file.getName());
return model;
}
Kindly let me know where i'm mistaking
in my Sping-servlet.xml i have defined multipartResolver as
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- setting maximum upload size -->
<property name="maxUploadSize" value="100000" />
</bean>
Let me know if anything else is required.
i think your form should have an attribute enctype like the following :
enctype="multipart/form-data"
if you are uploading file , you Use the #RequestParam for your file and for the other form fields that you have , like the following :
#RequestMapping(value="/upload", method=RequestMethod.POST)
public #ResponseBody String handleFileUpload(#RequestParam("name") String name,
#RequestParam("file") MultipartFile file){
}
in this example that is from the spring documentation , the handleFileUpload takes two parameters , the first is a normal String name , that is a normal field , the second is a file MultipartFile that is the file you want to upload .
Hope that Helps .

Resources