I am trying to upload a file to a server so i am trying to use #RequestBody to get the data of the file, but i am getting 415 error code while trying to upload a file.
So i have googled(got solution to upload a file) and got to know that i cant get file data from a request body. So i want to know why cant we access file data from request body as data will be sent in request body in HTTP requests, so i want to know how is the request happening in the case of uploading a file.
My server code before:
#RequestMapping(value = "/upload",headers = "Content-Type=multipart/form-data", method = RequestMethod.POST)
#ResponseBody
public String upload(#RequestBody MultipartFile file)
{
}
Solution:
#RequestMapping(value = "/upload",headers = "Content-Type=multipart/form-data", method = RequestMethod.POST)
#ResponseBody
public String upload(MultipartHttpServletRequest request)
{
}
Technically you could write your own HttpMessageConverter which would parse the full multipart request body, but you'd have to have a very specific target type that could handle all the parts.
You'll notice from the javadoc of #RequestBody
Annotation indicating a method parameter should be bound to the body
of the web request.
that the intention is to bind the entirety of the request body to the method parameter. How do you bind every part of a multipart request to a single parameter? Something like a MultiValueMap<String, Object> (which is what FormHttpMessageConverter uses when writing a multipart request). But that wouldn't be very useful because you'd have to check the type of each value.
It makes much more sense as a developer to specify exactly what you need. That's why #RequestParam and #RequestPart are available.
Because the files are not the request body, they are part of it and there is no built-in HttpMessageConverter that can convert the request to an array of MultiPartFile.
Thats why it works #RequestParam("file") MultipartFile[] files
instead of
#RequestBody MultipartFile file
Hope it helps.
Related
I'm currently working with creating a HttpRequestMessage and making a request with it. I have a collection of headers that I want to add to the request message.
I iterate through these headers and add them to the request with
message.Headers.Add(header, values);
However as part of my testing I'm finding that I get the following error thrown occassionaly (e.g. with Content-Length or Content-Type).
Misused header name. Make sure request headers are used with
HttpRequestMessage, response headers with HttpResponseMessage, and
content headers with HttpContent objects.
I've used a decompiler to look at HttpContentHeaders and HttpRequestHeaders and they both have an internal static method that populates a HashSet with a list of known headers, e.g.
internal static void AddKnownHeaders(HashSet<string> headerSet)
{
headerSet.Add("Allow");
headerSet.Add("Content-Disposition");
headerSet.Add("Content-Encoding");
// snip...
}
Is there a way to access the known/allowed headers for each of the types (content, request)? Reflection is an option but I'm wondering if there's another method to know where to add the headers?
I am in process of writing a junit for one of the controller methods with method signature as below:
#RequestMapping(value="/getTokenizedURL.json",method=RequestMethod.POST)
#ResponseBody
public ResponseData getTokenizedURL(#RequestBody final RequestData requestData, final HttpServletRequest request) throws CustomException
I need to call this method using MockMvc and I am able to call using below:
mockMvc.perform(post("/user/getTokenizedURL.json")
.contentType(MediaType.APPLICATION_JSON)
.content(json))
.andDo(print())
.andExpect(status().isOk());
But the problem is I am unable to setup HttpServletRequest Parameter while calling the original method using mock mvc. Without setting HttpServletRequest argument, my test is giving issues since it is something required and used with in original method.
Please let me know how should I setup the same. Thanks!
The idea is that you shouldn't need to.
MockMvcRequestBuilders#post(..) returns a MockHttpServletRequestBuilder which lets you construct the request with any values you want. These will be mirrored in the HttpServletRequest that gets passed to your handler method.
For example, you used
.contentType(MediaType.APPLICATION_JSON)
this will set the content-type header of the request. In your handler method, if you did
request.getHeader("content-type");
you'd get back a corresponding String for the MediaType.APPLICATION_JSON.
The MockHttpServletRequestBuilder has "setters" for every part of the request.
I am having a method test like below and making a RESTful webservice call to fetch the data,
#RequestMapping(value ="/select", method = RequestMethod.GET)
#ResponseBody
public String test(
#RequestParam(value="begin", defaultValue="0",required=false) final String begin
)
{
//Some java code
}
**RESTful Webservice Call:**
http://localhost:8081/a/b/c/select?begin=1
Returning the data properly
http://localhost:8081/a/b/c/select?begin:1
Here in the url = has been replaced with : for negative testing.
Here Spring ignores the given value 1 and picks the default value 0 and returns the data accordingly without errors
Question:
But I want to capture the actual URL field with value which is begin:1, do some validation and display error message that the url is incorrect.
I understood that begin:1 is not considered as part of url by spring and hence picks the default value. Wondering is there a way in Spring to capture the wrongly framed url's.
Any pointers would be helpful. Many Thanks!
I have a small question regarding Spring's MVC data binding capabilities.
I do have the following controller class:
#Controller
#RequestMapping("/foo")
public class FooController() {
// … some init stuff //
#RequestMapping(value = "/{id}/edit.{format}", method = RequestMethod.POST)
public ModelAndView editFoo(#RequestBody FooItem foo, #PathVariable("format") String format) {
// some code here to edit the FooItem //
}
}
I want to be able to post form data as well as XML against this method. For that to work I added two message converters to my applicationContext.xml: The default formHttpMessageConverter and an XStream marshaller.
This works fine, but I have a problem, that if I use #RequestBody and post form data against the URL, the server responds with a 415 Error. If I remove this annotation, form data works well and Spring creates the object for me, but if I post XML against it, I get an empty object.
Is there any way around this or do I need to have 2 methods to be able to handle both of the incoming formats?
Thanks in advance!
I think you need two methods.
FormHttpMessageConverter doesn't have the same databinding capabilities as #ModelAttribute provides, it can't bind request to the specified target class, only to MultiValueMap (see javadoc).
recently we moved to spring 3.0 Controller handling like this:
#Controller
public class MyController {
#RequestMapping(method = RequestMethod.POST)
protected String onSubmit ( Form form, Errors errors) {
// handle POST
}
#RequestMapping(method = RequestMethod.GET)
protected void getForm ( Form form ) {
// handle GET
}
}
Now we are getting lots of Exceptions in our logs because of HEAD Requests.
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'HEAD' not supported
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodResolver.resolveHandlerMethod(AnnotationMethodHandlerAdapter.java:621)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:422)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:415)
...
I would like to support HEAD Requests the same way like GET Requests, but obeying the HTTP reference of course:
The HEAD method is identical to GET
except that the server MUST NOT
return a message-body in the response.
The metainformation contained in
the HTTP headers in response to a HEAD
request SHOULD be identical to the
information sent in response to a GET
request. This method can be used
for obtaining metainformation about
the entity implied by the request
without transferring the entity-body
itself. This method is often used
for testing hypertext links for
validity, accessibility, and recent
modification.
http://www.ietf.org/rfc/rfc2616.txt
Does anybody has an elegant solution or is there even a spring solution out-of-the-box?
I searched the web but did not find any answers to this.
I believe this is what you're looking for:
http://www.axelfontaine.com/2009/09/transparently-supporting-http-head.html
In the current Spring (4.3.10) HEAD is automatically supported:
#RequestMapping methods mapped to "GET" are also implicitly mapped to
"HEAD", i.e. there is no need to have "HEAD" explicitly declared. An
HTTP HEAD request is processed as if it were an HTTP GET except
instead of writing the body only the number of bytes are counted and
the "Content-Length" header set.
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestmapping-head-options
Just add HEAD as a supported method the the request mapping:
#RequestMapping(method = {RequestMethod.GET, RequestMethod.HEAD})
Update: I think you can provide a custom class that extends AnnotationMethodHandlerAdapter to be the method handler (in dispatcher-servlet.xml), and just bypass the HEAD support check there. But I'd just use the replace features of an IDE to add it.