|
|
|
|
@ -1112,9 +1112,8 @@ public class RelativePathUriTemplateController {
@@ -1112,9 +1112,8 @@ public class RelativePathUriTemplateController {
|
|
|
|
|
<listitem> |
|
|
|
|
<para><interfacename>@RequestPart</interfacename> 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 |
|
|
|
|
<interfacename>HttpMessageConverter</interfacename>s. See <xref |
|
|
|
|
linkend="mvc-ann-requestpart" />.</para> |
|
|
|
|
See <xref linkend="mvc-multipart-forms-non-browsers" /> and |
|
|
|
|
<xref linkend="mvc-multipart"/>.</para> |
|
|
|
|
</listitem> |
|
|
|
|
|
|
|
|
|
<listitem> |
|
|
|
|
@ -1415,67 +1414,6 @@ public void handle(@RequestBody String body, Writer writer) throws IOException {
@@ -1415,67 +1414,6 @@ public void handle(@RequestBody String body, Writer writer) throws IOException {
|
|
|
|
|
</note> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="mvc-ann-requestpart"> |
|
|
|
|
<title>Mapping the content of a part of a "multipart/form-data" request with the |
|
|
|
|
<interfacename>@RequestPart</interfacename> annotation</title> |
|
|
|
|
|
|
|
|
|
<para>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 <xref linkend="mvc-multipart"/> -- but can also be used to send or receive |
|
|
|
|
a request with multiple types of content.</para> |
|
|
|
|
|
|
|
|
|
<para>The <interfacename>@RequestPart</interfacename> annotation works very similarly to the |
|
|
|
|
<interfacename>@RequestBody</interfacename> 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:</para> |
|
|
|
|
|
|
|
|
|
<programlisting language="java"> |
|
|
|
|
@RequestMapping(value="/configurations", method = RequestMethod.POST) |
|
|
|
|
public String onSubmit(<emphasis role="bold">@RequestPart("meta-data") MetaData metadata</emphasis>) { |
|
|
|
|
|
|
|
|
|
<lineannotation>// ...</lineannotation> |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
</programlisting> |
|
|
|
|
|
|
|
|
|
<para>The actual request may look like this:</para> |
|
|
|
|
|
|
|
|
|
<programlisting language="xml"> |
|
|
|
|
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 ... |
|
|
|
|
</programlisting> |
|
|
|
|
|
|
|
|
|
<para>In the above example, the <literal>metadata</literal> argument is bound to the content |
|
|
|
|
of the first part of the request called <literal>"meta-data"</literal> containing JSON content. |
|
|
|
|
In this case we specified the name of the request part in the |
|
|
|
|
<interfacename>@RequestPart</interfacename> annotation but we might have been able to leave it |
|
|
|
|
out if the name of the method argument matched the request part name.</para> |
|
|
|
|
|
|
|
|
|
<para>Just like with <interfacename>@RequestBody</interfacename> you convert the content of |
|
|
|
|
the request part to the method argument type by using an |
|
|
|
|
<classname>HttpMessageConverter</classname>. Also you can add <literal>@Valid</literal> |
|
|
|
|
to the method argument to have the resulting object automatically validated. |
|
|
|
|
If validation fails a <classname>RequestPartNotValidException</classname> is raised. |
|
|
|
|
The exception is handled by the <classname>DefaultHandlerExceptionResolver</classname> and |
|
|
|
|
results in a <literal>400</literal> error sent back to the client along with a message |
|
|
|
|
containing the validation errors.</para> |
|
|
|
|
|
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="mvc-ann-responsebody"> |
|
|
|
|
<title>Mapping the response body with the <interfacename>@ResponseBody</interfacename> |
|
|
|
|
annotation</title> |
|
|
|
|
@ -3037,9 +2975,10 @@ background=/themes/cool/img/coolBg.jpg</programlisting>
@@ -3037,9 +2975,10 @@ background=/themes/cool/img/coolBg.jpg</programlisting>
|
|
|
|
|
applications. You enable this multipart support with pluggable |
|
|
|
|
<interfacename>MultipartResolver</interfacename> objects, defined in the |
|
|
|
|
<literal>org.springframework.web.multipart</literal> package. Spring |
|
|
|
|
provides a <interfacename>MultipartResolver</interfacename> for use with |
|
|
|
|
<ulink url="http://jakarta.apache.org/commons/fileupload"> |
|
|
|
|
<emphasis>Commons FileUpload</emphasis></ulink>).</para> |
|
|
|
|
provides one <interfacename>MultipartResolver</interfacename> implementation |
|
|
|
|
for use with <ulink url="http://jakarta.apache.org/commons/fileupload"> |
|
|
|
|
<emphasis>Commons FileUpload</emphasis></ulink> and another for use |
|
|
|
|
with Servlet 3.0 multipart request parsing.</para> |
|
|
|
|
|
|
|
|
|
<para>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</programlisting>
@@ -3052,9 +2991,9 @@ background=/themes/cool/img/coolBg.jpg</programlisting>
|
|
|
|
|
treated like any other attribute.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="mvc-multipart-resolver"> |
|
|
|
|
<title>Using the |
|
|
|
|
<interfacename>MultipartResolver</interfacename></title> |
|
|
|
|
<section id="mvc-multipart-resolver-commons"> |
|
|
|
|
<title>Using a <interfacename>MultipartResolver</interfacename> |
|
|
|
|
with <emphasis>Commons FileUpload</emphasis></title> |
|
|
|
|
|
|
|
|
|
<para>The following example shows how to use the |
|
|
|
|
<classname>CommonsMultipartResolver</classname>:</para> |
|
|
|
|
@ -3082,6 +3021,33 @@ background=/themes/cool/img/coolBg.jpg</programlisting>
@@ -3082,6 +3021,33 @@ background=/themes/cool/img/coolBg.jpg</programlisting>
|
|
|
|
|
get access to the multipart files themselves in your controllers.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="mvc-multipart-resolver-standard"> |
|
|
|
|
<title>Using a <interfacename>MultipartResolver</interfacename> |
|
|
|
|
with <emphasis>Servlet 3.0</emphasis></title> |
|
|
|
|
|
|
|
|
|
<para>In order to use Servlet 3.0 based multipart parsing, |
|
|
|
|
you need to mark the <classname>DispatcherServlet</classname> with a |
|
|
|
|
<literal>"multipart-config"</literal> section in |
|
|
|
|
<filename>web.xml</filename>, or with a |
|
|
|
|
<classname>javax.servlet.MultipartConfigElement</classname> in |
|
|
|
|
programmatic servlet registration, or in case of a custom servlet class |
|
|
|
|
possibly with a <classname>javax.servlet.annotation.MultipartConfig</classname> |
|
|
|
|
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.</para> |
|
|
|
|
|
|
|
|
|
<para>Once Servlet 3.0 multipart parsing has been enabled |
|
|
|
|
in one of the above mentioned ways you can add the |
|
|
|
|
<classname>StandardServletMultipartResolver</classname> |
|
|
|
|
to your Spring configuration:</para> |
|
|
|
|
|
|
|
|
|
<programlisting language="xml"><bean id="multipartResolver" |
|
|
|
|
class="org.springframework.web.multipart.support.StandardServletMultipartResolver"> |
|
|
|
|
</bean></programlisting> |
|
|
|
|
|
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="mvc-multipart-forms"> |
|
|
|
|
<title>Handling a file upload in a form</title> |
|
|
|
|
|
|
|
|
|
@ -3115,7 +3081,7 @@ background=/themes/cool/img/coolBg.jpg</programlisting>
@@ -3115,7 +3081,7 @@ background=/themes/cool/img/coolBg.jpg</programlisting>
|
|
|
|
|
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 {
@@ -3134,18 +3100,92 @@ public class FileUpoadController {
|
|
|
|
|
example, nothing is done with the <literal>byte[]</literal>, but in |
|
|
|
|
practice you can save it in a database, store it on the file system, and |
|
|
|
|
so on.</para> |
|
|
|
|
|
|
|
|
|
<para>When using Servlet 3.0 multipart parsing you can also use |
|
|
|
|
<classname>javax.servlet.http.Part</classname> for the method parameter: |
|
|
|
|
<programlisting language="java">@Controller |
|
|
|
|
public class FileUpoadController { |
|
|
|
|
|
|
|
|
|
<para>Finally, you will have to declare the controller and the resolver |
|
|
|
|
in the application context:</para> |
|
|
|
|
@RequestMapping(value = "/form", method = RequestMethod.POST) |
|
|
|
|
public String handleFormUpload(@RequestParam("name") String name, |
|
|
|
|
@RequestParam("file") Part file) { |
|
|
|
|
|
|
|
|
|
<programlisting language="xml"><beans> |
|
|
|
|
<bean id="multipartResolver" |
|
|
|
|
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/> |
|
|
|
|
<lineannotation><!-- Declare explicitly, or use <context:annotation-config/> --></lineannotation> |
|
|
|
|
<bean id="fileUploadController" class="examples.FileUploadController"/> |
|
|
|
|
InputStream inputStream = file.getInputStream(); |
|
|
|
|
<lineannotation>// store bytes from uploaded file somewhere</lineannotation> |
|
|
|
|
|
|
|
|
|
return "redirect:uploadSuccess"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}</programlisting></para> |
|
|
|
|
|
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="mvc-multipart-forms-non-browsers"> |
|
|
|
|
<title>Handling a file upload request from programmatic clients</title> |
|
|
|
|
|
|
|
|
|
<para>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: |
|
|
|
|
<programlisting language="xml"> |
|
|
|
|
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 ... |
|
|
|
|
</programlisting></para> |
|
|
|
|
|
|
|
|
|
<para>You could access the part named "meta-data" with |
|
|
|
|
<interfacename>@RequestParam("meta-data") String metadata</interfacename> |
|
|
|
|
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 |
|
|
|
|
<interfacename>@RequestBody</interfacename> converts |
|
|
|
|
the body of a non-multipart requests to a target object |
|
|
|
|
with the help of an <classname>HttpMessageConverter</classname>.</para> |
|
|
|
|
|
|
|
|
|
<para>You can use the <interfacename>@RequestPart</interfacename> |
|
|
|
|
annotation instead of the <interfacename>@RequestParam</interfacename> |
|
|
|
|
annotation for this purpose. It allows you to have the |
|
|
|
|
content of a specific multipart passed through an |
|
|
|
|
<classname>HttpMessageConverter</classname> |
|
|
|
|
taking into consideration the <literal>'Content-Type'</literal> |
|
|
|
|
header of the multipart: |
|
|
|
|
<programlisting language="java"> |
|
|
|
|
@RequestMapping(value="/someUrl", method = RequestMethod.POST) |
|
|
|
|
public String onSubmit(<emphasis role="bold">@RequestPart("meta-data") MetaData metadata, |
|
|
|
|
@RequestPart("file-data") MultipartFile file,</emphasis>) { |
|
|
|
|
<lineannotation>// ...</lineannotation> |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
</programlisting></para> |
|
|
|
|
|
|
|
|
|
<para>Notice how you <classname>MultipartFile</classname> |
|
|
|
|
method arguments can be accessed with <interfacename>@RequestParam</interfacename> |
|
|
|
|
or with <interfacename>@RequestPart</interfacename> interchangeably. |
|
|
|
|
However, the <literal>@RequestPart("meta-data") MetaData</literal> |
|
|
|
|
method argument in this case is read as JSON content |
|
|
|
|
based on its <literal>'Content-Type'</literal> |
|
|
|
|
header and converted with help of the |
|
|
|
|
<classname>MappingJacksonHttpMessageConverter</classname>. |
|
|
|
|
</para> |
|
|
|
|
|
|
|
|
|
</beans></programlisting> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="mvc-exceptionhandlers"> |
|
|
|
|
|