From f4b7cfea38712035a7641d90477b9640d3204968 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 26 Jul 2011 15:49:44 +0000 Subject: [PATCH] SPR-8483 Update reference documentation with multipart request-related changes: @RequestPart, Servlet 3.0 multipart reuqests, javax.servlet.http.Part method argument types. --- spring-framework-reference/src/mvc.xml | 198 +++++++++++++++---------- 1 file changed, 119 insertions(+), 79 deletions(-) diff --git a/spring-framework-reference/src/mvc.xml b/spring-framework-reference/src/mvc.xml index cf80b6ceb4..25c243e894 100644 --- a/spring-framework-reference/src/mvc.xml +++ b/spring-framework-reference/src/mvc.xml @@ -1112,9 +1112,8 @@ public class RelativePathUriTemplateController { @RequestPart annotated parameters for access to the content of a "multipart/form-data" request part. - Parameter values are converted to the declared method argument type using - HttpMessageConverters. See . + See and + . @@ -1415,67 +1414,6 @@ public void handle(@RequestBody String body, Writer writer) throws IOException { -
- Mapping the content of a part of a "multipart/form-data" request with the - <interfacename>@RequestPart</interfacename> annotation - - A "multipart/form-data" request contains a series of parts each with its own - headers and content. It is commonly used for handling file uploads on a form -- - see -- but can also be used to send or receive - a request with multiple types of content. - - The @RequestPart annotation works very similarly to the - @RequestBody annotation except instead of looking in the - body of the HTTP request, it binds the method parameter to the content of one of the - parts of a "multipart/form-data" request. Here is an exampe: - - -@RequestMapping(value="/configurations", method = RequestMethod.POST) -public String onSubmit(@RequestPart("meta-data") MetaData metadata) { - - // ... - -} - - - The actual request may look like this: - - -POST /configurations -Content-Type: multipart/mixed - ---edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp -Content-Disposition: form-data; name="meta-data" -Content-Type: application/json; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -{ - "name": "value" -} ---edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp -Content-Disposition: form-data; name="file-data"; filename="file.properties" -Content-Type: text/xml -Content-Transfer-Encoding: 8bit -... File Data ... - - - In the above example, the metadata argument is bound to the content - of the first part of the request called "meta-data" containing JSON content. - In this case we specified the name of the request part in the - @RequestPart annotation but we might have been able to leave it - out if the name of the method argument matched the request part name. - - Just like with @RequestBody you convert the content of - the request part to the method argument type by using an - HttpMessageConverter. Also you can add @Valid - to the method argument to have the resulting object automatically validated. - If validation fails a RequestPartNotValidException is raised. - The exception is handled by the DefaultHandlerExceptionResolver and - results in a 400 error sent back to the client along with a message - containing the validation errors. - -
-
Mapping the response body with the <interfacename>@ResponseBody</interfacename> annotation @@ -3037,9 +2975,10 @@ background=/themes/cool/img/coolBg.jpg applications. You enable this multipart support with pluggable MultipartResolver objects, defined in the org.springframework.web.multipart package. Spring - provides a MultipartResolver for use with - - Commons FileUpload). + provides one MultipartResolver implementation + for use with + Commons FileUpload and another for use + with Servlet 3.0 multipart request parsing. By default, Spring does no multipart handling, because some developers want to handle multiparts themselves. You enable Spring @@ -3052,9 +2991,9 @@ background=/themes/cool/img/coolBg.jpg treated like any other attribute.
-
- Using the - <interfacename>MultipartResolver</interfacename> +
+ Using a <interfacename>MultipartResolver</interfacename> + with <emphasis>Commons FileUpload</emphasis> The following example shows how to use the CommonsMultipartResolver: @@ -3082,6 +3021,33 @@ background=/themes/cool/img/coolBg.jpg get access to the multipart files themselves in your controllers.
+
+ Using a <interfacename>MultipartResolver</interfacename> + with <emphasis>Servlet 3.0</emphasis> + + In order to use Servlet 3.0 based multipart parsing, + you need to mark the DispatcherServlet with a + "multipart-config" section in + web.xml, or with a + javax.servlet.MultipartConfigElement in + programmatic servlet registration, or in case of a custom servlet class + possibly with a javax.servlet.annotation.MultipartConfig + annotation on your servlet class. Configuration settings such as + maximum sizes or storage locations need to be applied at that + servlet registration level as Servlet 3.0 does not allow for + those settings to be done from the MultipartResolver. + + Once Servlet 3.0 multipart parsing has been enabled + in one of the above mentioned ways you can add the + StandardServletMultipartResolver + to your Spring configuration: + + <bean id="multipartResolver" + class="org.springframework.web.multipart.support.StandardServletMultipartResolver"> +</bean> + +
+
Handling a file upload in a form @@ -3115,7 +3081,7 @@ background=/themes/cool/img/coolBg.jpg public class FileUpoadController { @RequestMapping(value = "/form", method = RequestMethod.POST) - public String handleFormUpload(@RequestParam("name") String name, + public String handleFormUpload(@RequestParam("name") String name, @RequestParam("file") MultipartFile file) { if (!file.isEmpty()) { @@ -3134,18 +3100,92 @@ public class FileUpoadController { example, nothing is done with the byte[], but in practice you can save it in a database, store it on the file system, and so on. + + When using Servlet 3.0 multipart parsing you can also use + javax.servlet.http.Part for the method parameter: + @Controller +public class FileUpoadController { - Finally, you will have to declare the controller and the resolver - in the application context: + @RequestMapping(value = "/form", method = RequestMethod.POST) + public String handleFormUpload(@RequestParam("name") String name, + @RequestParam("file") Part file) { - <beans> - <bean id="multipartResolver" - class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/> - <!-- Declare explicitly, or use <context:annotation-config/> --> - <bean id="fileUploadController" class="examples.FileUploadController"/> + InputStream inputStream = file.getInputStream(); + // store bytes from uploaded file somewhere + + return "redirect:uploadSuccess"; + } + +} + +
+ +
+ Handling a file upload request from programmatic clients + + Multipart requests can also be submitted from non-browser clients in + a RESTful service scenario. All of the above examples and configuration + apply here as well. However, unlike browsers that typically submit files + and simple form fields, a programmatic client can also send more complex + data of a specific content type -- for exmaple a multipart request with + a file and second part with JSON formatted data: + +POST /someUrl +Content-Type: multipart/mixed + +--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp +Content-Disposition: form-data; name="meta-data" +Content-Type: application/json; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +{ + "name": "value" +} +--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp +Content-Disposition: form-data; name="file-data"; filename="file.properties" +Content-Type: text/xml +Content-Transfer-Encoding: 8bit +... File Data ... + + + You could access the part named "meta-data" with + @RequestParam("meta-data") String metadata + controller method argument. However, you would probably + prefer to accept a strongly typed object initialized + from the JSON formatted data in the body of the request + part, very similar to the way + @RequestBody converts + the body of a non-multipart requests to a target object + with the help of an HttpMessageConverter. + + You can use the @RequestPart + annotation instead of the @RequestParam + annotation for this purpose. It allows you to have the + content of a specific multipart passed through an + HttpMessageConverter + taking into consideration the 'Content-Type' + header of the multipart: + +@RequestMapping(value="/someUrl", method = RequestMethod.POST) +public String onSubmit(@RequestPart("meta-data") MetaData metadata, + @RequestPart("file-data") MultipartFile file,) { + // ... + +} + + + Notice how you MultipartFile + method arguments can be accessed with @RequestParam + or with @RequestPart interchangeably. + However, the @RequestPart("meta-data") MetaData + method argument in this case is read as JSON content + based on its 'Content-Type' + header and converted with help of the + MappingJacksonHttpMessageConverter. + -</beans>
+
-- GitLab