I'm having trouble doing an ajax POST to a Spring Controller using jquery.
The post contains several parameters, among which is a base 64 string that represents a file sent from the client side.
Now, if the file is under 1,5~2mb, the request gets done just fine.
If it surpasses this size, the controller returns that the request is syntatically incorrect.
I'm using encodeuricomponent in the client side.
In both scenarios, if I get the reader from the HTTPServletRequest, I can get the entire POST form. Needless tosay, it's super slow.
If the file is above 2 mb, I can also get the entire query by the method referenced above, but not by the getParameter() method(HTTPServletRequest) nor by annotations (#requestParam("file")).
This is my controller:
#ResponseBody
#RequestMapping(value="/uploadClient", method = RequestMethod.POST)
public String uploadClient( Model model, HttpServletRequest req,#RequestParam(value="file", required = false) String file, #RequestParam(value="projectID") Integer projectID,
#RequestParam(value="opID") Integer opID, #RequestParam(value="releaseID") Integer releaseID,
#RequestParam(value="name") String name, #RequestParam(value="url") String url,
#RequestParam(value="date") String date,
#RequestParam(value="version") String version, #RequestParam(value="comment") String comment,
#RequestParam(value="fileName") String fileName){
For uploading files using Spring, try using the multipart support. Refer to the link Spring's multipart (fileupload) support
Related
I want to test a RequestMapping which takes some information about an item and then persists it, it also allows for images to be uploaded. However, the image uploading is not mandatory and my HTML form is using: enctype="multipart/form-data". I am trying to test the controller without actually uploading any files, the controller looks like this:
#RequestMapping(value="/admin/upload", method=RequestMethod.POST)
public ModelAndView addItem(
#RequestParam(value="id", required=true) Integer id,
#RequestParam(value="name", required=true) String name,
#RequestParam(value="image", required=false) MultipartFile file,
) throws IOException {
// some stuff here
ModelAndView mov = new ModelAndView();
return mov;
}
Even though I've set the required flag to be false I am getting the issue of a missing parameter, but more importantly, is it possible to send headers in the mockMvc request which would allow me to test this mapping without the need for uploading any images?
mockMvc.perform(post("https://localhost/store-admin/items/itemAddSubmit")
.param("id", 1)
.param("name", "testname").with(csrf()))
.andDo(print());
For multipart request you need to use fileUpload method instead of get, post or whatever.
Update your code as follows -
mockMvc.perform(fileUpload("https://localhost/store-admin/items/itemAddSubmit")
.param("id", 1)
.param("name", "testname").with(csrf()))
.andDo(print());
To actually send a file use the file function with fileUpload as shown below -
mockMvc.perform(fileUpload("https://localhost/store-admin/items/itemAddSubmit")
.file(myMockMultipartFile)
.param("id", 1)
.param("name", "testname").with(csrf()))
.andDo(print());
where myMockMultipartFile is a MockMultipartFile object.
Very important to note - if the [#RequestParam that accepts the file] on your REST endpoint doesn't have a "value=" attribute set, it will also throw the same type of an error when running a mock test. You could have ignored the "value" attribute when running the solution in prod and not experienced any error, but doing so would prevent you from running a test and injecting in the file programmatically.
Ex:
#RequestParam(value="file") final MultipartFile file,
Your question already showed this properly, but I want to document this answer for users in the future who may, like myself, overlook such a small detail.
Cheers
I have a Spring REST application that accepts JSON messages, written like
#RequestMapping(value = "/myhook", method = RequestMethod.POST,
produces = JSON, consumes = JSON)
public #ResponseBody MyResponse doIt
(#Valid #RequestBody(required = true) MyContractRequest request) {
MyResponse response;
...
return response;
}
This works really well with almost no code to support, but now I have a requirement to sign both response and request.
I started from simply computing the shared signature of all message fields at Java level and assigning it to the dedicated signature field. However this requires to have and maintain code for computing the signatures:
public void update(java.security.Signature sign) throws Exception {
sign.update(name);
sign.update(value);
sign.update(etc);
}
Some people around me expressed opinion that the need to write and maintain this signing code may not be the best design, and it may be better to sign the whole message as a single JSON string. I could fetch the request as a string manually, and then process JSON manually, but I really would like to preserve the Spring controller concepts.
Also, I cannot longer have the signature field in the message itself because the value of this field obviously also changes the signature of the JSON string.
Is there any way to compute the signature of the whole JSON message body on the message departure and arrival, and where to place the signature so it could be passed together with the message? One of the idea is to use the custom HTTP header for the signature. Anyway, how to compute it first?
You can use a servlet filter with Spring MVC and modified your content whatever you want in request and response as well
Example :
http://www.mkyong.com/spring-mvc/how-to-register-a-servlet-filter-in-spring-mvc/
or you can use Spring 3 MVC Interceptor
http://viralpatel.net/blogs/spring-mvc-interceptor-example/
In a controller class,
I have one method
#RequestMapping(value="test", method={RequestMethod.POST,RequestMethod.PUT})
#ResponseBody
public String testApp(#RequestParam String priceA, #RequestBody String valueOfProduct) throws Exception {
}
My client is sending prices to my App as POST requests for processing.
Now client (which is not under my control) is planning to send the price value as a request parameter and another client is planning to send price in requestheader.
The trick is:
If it is present in requestheader it wont be present in requestparameter.
So I have to design it such that my server code works fine in both cases.
Kindly let me know which design would be the best.
Will it be
#RequestMapping(value="test", method={RequestMethod.POST,RequestMethod.PUT})
#ResponseBody
public String testApp(#RequestParam String priceA, #RequestHeader("PRICE") String priceAFromAnother, #RequestBody String valueOfProduct) throws Exception {
}
But above logic wont work as #RequestParam wont be available all the time.
Have you tried searching by your own first?
Take a look that this answer.
If you know the header to search for, you could add a request filter (HttpServletRequestWrapper) that pre-process the request. Here is simple example Modify request parameter with servlet filter
NOTE: I would caution you that this methodology is not maintainable if your parameter set/api is going to grow over time.
I'm trying to build an API that takes a POST with one parameter in the body that should be x-www-form-urlencoded. I've currently mapped it as:
#RequestMapping(method = POST, consumes = APPLICATION_FORM_URLENCODED_VALUE, produces = APPLICATION_JSON_VALUE)
public ResponseEntity<LinkEntity> createShortLink(#RequestBody String url) {
LinkEntity savedLink = linkService.create(url);
}
When I do a POST with Postman (REST Chrome extension) with one form parameter url=http://www.drissamri.be it comes into this method as url=http%3A%2F%2Fwww.drissamri.be as expected.
When I try to change the #Requestbody into #RequestParam(value = "url") I still get the URL with the url= prefix (as expected) but it is not urlencoded anymore. Why doesn't the encoding take place any more? Is this a bug or is there another way to take in the parameter as urlencoded value
As correctly mentioned by Pavel Horal the parameter is retrieved by ServletRequest#getParameter and is already decoded. If you need to access the origin parameter you can access the parameter by other means.
One way would be to inject a HttpServletRequest and use HttpServletRequest#getQueryString() which does not decode the values.
I have an application using spring-mvc 3.0.
The controllers are configured like this:
#RequestMapping(value = "/update", method = RequestMethod.POST)
public ModelAndView updateValues(
#RequestParam("einvoiceId") String id){
...}
When posting an id that contains special characters (in this case pipe |), url-encoded with UTF-8 (id=000025D26A01%7C2014174) the string id will contain %7C. I was expecting spring-mvc to url decode the parameter. I am aware that I can solve this by using
java.net.URLDecoder.decode()
but since I have a large number of controllers, I would like this to be done automatically by the framework.
I have configured the Tomcat connector with URIEncoding="UTF-8" and configured a CharacterEncodingFilter, but as I understand it this will only affect GET requests.
Any ideas on how I can make spring-mvc url decode my post parameters?
http://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q3
This page says CharacterEncodingFilter can change POST parameters
I believe you encounter the same issue as I did.
Try using #PathVariable instead #RequestParam.
#PathVariable is to obtain some placeholder from the uri (Spring call it an URI Template) — see Spring Reference Chapter 16.3.2.2 URI Template Patterns
If you do, you have to change your url and don't provide parameter 'id'.
Just "/update/000025D26A01%7C2014174".
More information can be found where I found the solution for my problem #RequestParam vs #PathVariable