SPR-8483 Update reference documentation with multipart request-related changes: @RequestPart, Servlet 3.0 multipart reuqests, javax.servlet.http.Part method argument types.
This commit is contained in:
parent
75ad185558
commit
f4b7cfea38
|
|
@ -1112,9 +1112,8 @@ public class RelativePathUriTemplateController {
|
||||||
<listitem>
|
<listitem>
|
||||||
<para><interfacename>@RequestPart</interfacename> annotated parameters
|
<para><interfacename>@RequestPart</interfacename> annotated parameters
|
||||||
for access to the content of a "multipart/form-data" request part.
|
for access to the content of a "multipart/form-data" request part.
|
||||||
Parameter values are converted to the declared method argument type using
|
See <xref linkend="mvc-multipart-forms-non-browsers" /> and
|
||||||
<interfacename>HttpMessageConverter</interfacename>s. See <xref
|
<xref linkend="mvc-multipart"/>.</para>
|
||||||
linkend="mvc-ann-requestpart" />.</para>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|
@ -1415,67 +1414,6 @@ public void handle(@RequestBody String body, Writer writer) throws IOException {
|
||||||
</note>
|
</note>
|
||||||
</section>
|
</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">
|
<section id="mvc-ann-responsebody">
|
||||||
<title>Mapping the response body with the <interfacename>@ResponseBody</interfacename>
|
<title>Mapping the response body with the <interfacename>@ResponseBody</interfacename>
|
||||||
annotation</title>
|
annotation</title>
|
||||||
|
|
@ -3037,9 +2975,10 @@ background=/themes/cool/img/coolBg.jpg</programlisting>
|
||||||
applications. You enable this multipart support with pluggable
|
applications. You enable this multipart support with pluggable
|
||||||
<interfacename>MultipartResolver</interfacename> objects, defined in the
|
<interfacename>MultipartResolver</interfacename> objects, defined in the
|
||||||
<literal>org.springframework.web.multipart</literal> package. Spring
|
<literal>org.springframework.web.multipart</literal> package. Spring
|
||||||
provides a <interfacename>MultipartResolver</interfacename> for use with
|
provides one <interfacename>MultipartResolver</interfacename> implementation
|
||||||
<ulink url="http://jakarta.apache.org/commons/fileupload">
|
for use with <ulink url="http://jakarta.apache.org/commons/fileupload">
|
||||||
<emphasis>Commons FileUpload</emphasis></ulink>).</para>
|
<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
|
<para>By default, Spring does no multipart handling, because some
|
||||||
developers want to handle multiparts themselves. You enable Spring
|
developers want to handle multiparts themselves. You enable Spring
|
||||||
|
|
@ -3052,9 +2991,9 @@ background=/themes/cool/img/coolBg.jpg</programlisting>
|
||||||
treated like any other attribute.</para>
|
treated like any other attribute.</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="mvc-multipart-resolver">
|
<section id="mvc-multipart-resolver-commons">
|
||||||
<title>Using the
|
<title>Using a <interfacename>MultipartResolver</interfacename>
|
||||||
<interfacename>MultipartResolver</interfacename></title>
|
with <emphasis>Commons FileUpload</emphasis></title>
|
||||||
|
|
||||||
<para>The following example shows how to use the
|
<para>The following example shows how to use the
|
||||||
<classname>CommonsMultipartResolver</classname>:</para>
|
<classname>CommonsMultipartResolver</classname>:</para>
|
||||||
|
|
@ -3082,6 +3021,33 @@ background=/themes/cool/img/coolBg.jpg</programlisting>
|
||||||
get access to the multipart files themselves in your controllers.</para>
|
get access to the multipart files themselves in your controllers.</para>
|
||||||
</section>
|
</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">
|
<section id="mvc-multipart-forms">
|
||||||
<title>Handling a file upload in a form</title>
|
<title>Handling a file upload in a form</title>
|
||||||
|
|
||||||
|
|
@ -3115,7 +3081,7 @@ background=/themes/cool/img/coolBg.jpg</programlisting>
|
||||||
public class FileUpoadController {
|
public class FileUpoadController {
|
||||||
|
|
||||||
@RequestMapping(value = "/form", method = RequestMethod.POST)
|
@RequestMapping(value = "/form", method = RequestMethod.POST)
|
||||||
public String handleFormUpload(@RequestParam("name") String name,
|
public String handleFormUpload(@RequestParam("name") String name,
|
||||||
@RequestParam("file") MultipartFile file) {
|
@RequestParam("file") MultipartFile file) {
|
||||||
|
|
||||||
if (!file.isEmpty()) {
|
if (!file.isEmpty()) {
|
||||||
|
|
@ -3134,18 +3100,92 @@ public class FileUpoadController {
|
||||||
example, nothing is done with the <literal>byte[]</literal>, but in
|
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
|
practice you can save it in a database, store it on the file system, and
|
||||||
so on.</para>
|
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
|
@RequestMapping(value = "/form", method = RequestMethod.POST)
|
||||||
in the application context:</para>
|
public String handleFormUpload(@RequestParam("name") String name,
|
||||||
|
@RequestParam("file") Part file) {
|
||||||
|
|
||||||
<programlisting language="xml"><beans>
|
InputStream inputStream = file.getInputStream();
|
||||||
<bean id="multipartResolver"
|
<lineannotation>// store bytes from uploaded file somewhere</lineannotation>
|
||||||
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
|
|
||||||
<lineannotation><!-- Declare explicitly, or use <context:annotation-config/> --></lineannotation>
|
return "redirect:uploadSuccess";
|
||||||
<bean id="fileUploadController" class="examples.FileUploadController"/>
|
}
|
||||||
|
|
||||||
|
}</programlisting></para>
|
||||||
|
|
||||||
</beans></programlisting>
|
|
||||||
</section>
|
</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>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="mvc-exceptionhandlers">
|
<section id="mvc-exceptionhandlers">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue