public class FormHttpMessageConverter extends java.lang.Object implements HttpMessageConverter<MultiValueMap<java.lang.String,?>>
HttpMessageConverter
to read and write 'normal' HTML
forms and also to write (but not read) multipart data (e.g. file uploads).
In other words, this converter can read and write the
"application/x-www-form-urlencoded"
media type as
MultiValueMap<String, String>
and it can also
write (but not read) the "multipart/form-data"
media type as
MultiValueMap<String, Object>
.
When writing multipart data, this converter uses other
HttpMessageConverters
to write the respective
MIME parts. By default, basic converters are registered (for Strings
and Resources
). These can be overridden through the
partConverters
property.
For example, the following snippet shows how to submit an HTML form:
RestTemplate template = new RestTemplate(); // FormHttpMessageConverter is configured by default MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>(); form.add("field 1", "value 1"); form.add("field 2", "value 2"); form.add("field 2", "value 3"); template.postForLocation("http://example.com/myForm", form);
The following snippet shows how to do a file upload:
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>(); parts.add("field 1", "value 1"); parts.add("file", new ClassPathResource("myFile.jpg")); template.postForLocation("http://example.com/myFileUpload", parts);
Some methods in this class were inspired by
org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity
.
MultiValueMap
Modifier and Type | Class and Description |
---|---|
private static class |
FormHttpMessageConverter.MimeDelegate
Inner class to avoid a hard dependency on the JavaMail API.
|
private static class |
FormHttpMessageConverter.MultipartHttpOutputMessage
Implementation of
HttpOutputMessage used
to write a MIME multipart. |
Modifier and Type | Field and Description |
---|---|
private java.nio.charset.Charset |
charset |
static java.nio.charset.Charset |
DEFAULT_CHARSET |
private java.nio.charset.Charset |
multipartCharset |
private java.util.List<HttpMessageConverter<?>> |
partConverters |
private java.util.List<MediaType> |
supportedMediaTypes |
Constructor and Description |
---|
FormHttpMessageConverter() |
Modifier and Type | Method and Description |
---|---|
void |
addPartConverter(HttpMessageConverter<?> partConverter)
Add a message body converter.
|
private void |
applyDefaultCharset()
Apply the configured charset as a default to registered part converters.
|
boolean |
canRead(java.lang.Class<?> clazz,
MediaType mediaType)
Indicates whether the given class can be read by this converter.
|
boolean |
canWrite(java.lang.Class<?> clazz,
MediaType mediaType)
Indicates whether the given class can be written by this converter.
|
protected byte[] |
generateMultipartBoundary()
Generate a multipart boundary.
|
protected java.lang.String |
getFilename(java.lang.Object part)
Return the filename of the given multipart part.
|
protected HttpEntity<?> |
getHttpEntity(java.lang.Object part)
Return an
HttpEntity for the given part Object. |
java.util.List<MediaType> |
getSupportedMediaTypes()
Return the list of
MediaType objects supported by this converter. |
private boolean |
isFilenameCharsetSet()
When
setMultipartCharset(Charset) is configured (i.e. |
private boolean |
isMultipart(MultiValueMap<java.lang.String,?> map,
MediaType contentType) |
MultiValueMap<java.lang.String,java.lang.String> |
read(java.lang.Class<? extends MultiValueMap<java.lang.String,?>> clazz,
HttpInputMessage inputMessage)
Read an object of the given type from the given input message, and returns it.
|
void |
setCharset(java.nio.charset.Charset charset)
Set the default character set to use for reading and writing form data when
the request or response Content-Type header does not explicitly specify it.
|
void |
setMultipartCharset(java.nio.charset.Charset charset)
Set the character set to use when writing multipart data to encode file
names.
|
void |
setPartConverters(java.util.List<HttpMessageConverter<?>> partConverters)
Set the message body converters to use.
|
void |
setSupportedMediaTypes(java.util.List<MediaType> supportedMediaTypes)
Set the list of
MediaType objects supported by this converter. |
void |
write(MultiValueMap<java.lang.String,?> map,
MediaType contentType,
HttpOutputMessage outputMessage)
Write an given object to the given output message.
|
private void |
writeBoundary(java.io.OutputStream os,
byte[] boundary) |
private static void |
writeEnd(java.io.OutputStream os,
byte[] boundary) |
private void |
writeForm(MultiValueMap<java.lang.String,java.lang.String> form,
MediaType contentType,
HttpOutputMessage outputMessage) |
private void |
writeMultipart(MultiValueMap<java.lang.String,java.lang.Object> parts,
HttpOutputMessage outputMessage) |
private static void |
writeNewLine(java.io.OutputStream os) |
private void |
writePart(java.lang.String name,
HttpEntity<?> partEntity,
java.io.OutputStream os) |
private void |
writeParts(java.io.OutputStream os,
MultiValueMap<java.lang.String,java.lang.Object> parts,
byte[] boundary) |
public static final java.nio.charset.Charset DEFAULT_CHARSET
private java.util.List<MediaType> supportedMediaTypes
private java.util.List<HttpMessageConverter<?>> partConverters
private java.nio.charset.Charset charset
@Nullable private java.nio.charset.Charset multipartCharset
public void setSupportedMediaTypes(java.util.List<MediaType> supportedMediaTypes)
MediaType
objects supported by this converter.public java.util.List<MediaType> getSupportedMediaTypes()
HttpMessageConverter
MediaType
objects supported by this converter.getSupportedMediaTypes
in interface HttpMessageConverter<MultiValueMap<java.lang.String,?>>
public void setPartConverters(java.util.List<HttpMessageConverter<?>> partConverters)
public void addPartConverter(HttpMessageConverter<?> partConverter)
public void setCharset(@Nullable java.nio.charset.Charset charset)
As of 4.3, this is also used as the default charset for the conversion of text bodies in a multipart request.
As of 5.0 this is also used for part headers including
"Content-Disposition" (and its filename parameter) unless (the mutually
exclusive) setMultipartCharset(java.nio.charset.Charset)
is also set, in which case part
headers are encoded as ASCII and filename is encoded with the
"encoded-word" syntax from RFC 2047.
By default this is set to "UTF-8".
private void applyDefaultCharset()
public void setMultipartCharset(java.nio.charset.Charset charset)
MimeUtility
from "javax.mail".
As of 5.0 by default part headers, including Content-Disposition (and
its filename parameter) will be encoded based on the setting of
setCharset(Charset)
or UTF-8
by default.
public boolean canRead(java.lang.Class<?> clazz, @Nullable MediaType mediaType)
HttpMessageConverter
canRead
in interface HttpMessageConverter<MultiValueMap<java.lang.String,?>>
clazz
- the class to test for readabilitymediaType
- the media type to read (can be null
if not specified);
typically the value of a Content-Type
header.true
if readable; false
otherwisepublic boolean canWrite(java.lang.Class<?> clazz, @Nullable MediaType mediaType)
HttpMessageConverter
canWrite
in interface HttpMessageConverter<MultiValueMap<java.lang.String,?>>
clazz
- the class to test for writabilitymediaType
- the media type to write (can be null
if not specified);
typically the value of an Accept
header.true
if writable; false
otherwisepublic MultiValueMap<java.lang.String,java.lang.String> read(@Nullable java.lang.Class<? extends MultiValueMap<java.lang.String,?>> clazz, HttpInputMessage inputMessage) throws java.io.IOException, HttpMessageNotReadableException
HttpMessageConverter
read
in interface HttpMessageConverter<MultiValueMap<java.lang.String,?>>
clazz
- the type of object to return. This type must have previously been passed to the
canRead
method of this interface, which must have returned true
.inputMessage
- the HTTP input message to read fromjava.io.IOException
- in case of I/O errorsHttpMessageNotReadableException
- in case of conversion errorspublic void write(MultiValueMap<java.lang.String,?> map, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws java.io.IOException, HttpMessageNotWritableException
HttpMessageConverter
write
in interface HttpMessageConverter<MultiValueMap<java.lang.String,?>>
map
- the object to write to the output message. The type of this object must have previously been
passed to the canWrite
method of this interface, which must have returned true
.contentType
- the content type to use when writing. May be null
to indicate that the
default content type of the converter must be used. If not null
, this media type must have
previously been passed to the canWrite
method of this interface, which must have
returned true
.outputMessage
- the message to write tojava.io.IOException
- in case of I/O errorsHttpMessageNotWritableException
- in case of conversion errorsprivate boolean isMultipart(MultiValueMap<java.lang.String,?> map, @Nullable MediaType contentType)
private void writeForm(MultiValueMap<java.lang.String,java.lang.String> form, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws java.io.IOException
java.io.IOException
private void writeMultipart(MultiValueMap<java.lang.String,java.lang.Object> parts, HttpOutputMessage outputMessage) throws java.io.IOException
java.io.IOException
private boolean isFilenameCharsetSet()
setMultipartCharset(Charset)
is configured (i.e. RFC 2047,
"encoded-word" syntax) we need to use ASCII for part headers or otherwise
we encode directly using the configured setCharset(Charset)
.private void writeParts(java.io.OutputStream os, MultiValueMap<java.lang.String,java.lang.Object> parts, byte[] boundary) throws java.io.IOException
java.io.IOException
private void writePart(java.lang.String name, HttpEntity<?> partEntity, java.io.OutputStream os) throws java.io.IOException
java.io.IOException
protected byte[] generateMultipartBoundary()
This implementation delegates to
MimeTypeUtils.generateMultipartBoundary()
.
protected HttpEntity<?> getHttpEntity(java.lang.Object part)
HttpEntity
for the given part Object.part
- the part to return an HttpEntity
forHttpEntity
,
or a newly built HttpEntity
wrapper for that part@Nullable protected java.lang.String getFilename(java.lang.Object part)
Content-Disposition
header.
The default implementation returns Resource.getFilename()
if the part is a
Resource
, and null
in other cases. Can be overridden in subclasses.
part
- the part to determine the file name fornull
if not knownprivate void writeBoundary(java.io.OutputStream os, byte[] boundary) throws java.io.IOException
java.io.IOException
private static void writeEnd(java.io.OutputStream os, byte[] boundary) throws java.io.IOException
java.io.IOException
private static void writeNewLine(java.io.OutputStream os) throws java.io.IOException
java.io.IOException