mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-25 08:19:01 +00:00
Move multipart support to dedicated converter
Prior to this commit, gh-36255 introduced the new `MultipartHttpMessageConverter`, focusing on multipart message conversion in a separate converter. The `FormHttpMessageConverter` did conflate URL encoded forms and multipart messages in the same converter. With the introduction of the new converter and related types in the same package (with `Part`, `FormFieldPart` and `FilePart`), we can now revisit this arrangement. This commit restricts the `FormHttpMessageConverter` to URL encoded forms only and as a result, changes its implementation to only consider `MultiValueMap<String, String>` types for reading and writing HTTP messages. Because type erasure, this converter is now a `SmartHttpMessageConverter` to get better type information with `ResolvableType`. As a result, the `AllEncompassingFormHttpMessageConverter` is formally deprecated and replaced by the `MultipartHttpMessageConverter`, by setting part converters explicitly in its constructor. Closes gh-36256
This commit is contained in:
@@ -402,6 +402,27 @@ To serialize only a subset of the object properties, you can specify a {baeldung
|
||||
.toBodilessEntity();
|
||||
----
|
||||
|
||||
==== URL encoded Forms
|
||||
|
||||
URL encoded forms, using the `"application/x-www-form-urlencoded"` media type, are useful for sending String key/values over the wire.
|
||||
This is supported by the `FormHttpMessageConverter`, if the application uses a `MultiValueMap<String, String>` as source instance
|
||||
or a target type.
|
||||
|
||||
For example:
|
||||
|
||||
[source,java,indent=0,subs="verbatim"]
|
||||
----
|
||||
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
|
||||
form.add("project", "Spring Framework");
|
||||
form.add("module", "spring-web");
|
||||
ResponseEntity<Void> response = this.restClient.post()
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.body(form)
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
----
|
||||
|
||||
|
||||
==== Multipart
|
||||
|
||||
To send multipart data, you need to provide a `MultiValueMap<String, Object>` whose values may be an `Object` for part content, a `Resource` for a file part, or an `HttpEntity` for part content with headers.
|
||||
@@ -419,18 +440,22 @@ For example:
|
||||
headers.setContentType(MediaType.APPLICATION_XML);
|
||||
parts.add("xmlPart", new HttpEntity<>(myBean, headers));
|
||||
|
||||
// send using RestClient.post or RestTemplate.postForEntity
|
||||
ResponseEntity<Void> response = this.restClient.post()
|
||||
.contentType(MediaType.MULTIPART_FORM_DATA)
|
||||
.body(parts)
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
----
|
||||
|
||||
In most cases, you do not have to specify the `Content-Type` for each part.
|
||||
The content type is determined automatically based on the `HttpMessageConverter` chosen to serialize it or, in the case of a `Resource`, based on the file extension.
|
||||
If necessary, you can explicitly provide the `MediaType` with an `HttpEntity` wrapper.
|
||||
|
||||
Once the `MultiValueMap` is ready, you can use it as the body of a `POST` request, using `RestClient.post().body(parts)` (or `RestTemplate.postForObject`).
|
||||
The `Content-Type` is set to `multipart/form-data` by the `MultiPartHttpMessageConverter`.
|
||||
As seen in the previous section, `MultiValueMap` types can also be used for URL encoded forms.
|
||||
It is preferable to explicitly set the media type in the `Content-Type` or `Accept` HTTP request headers to ensure that the expected
|
||||
message converter is used.
|
||||
|
||||
If the `MultiValueMap` contains at least one non-`String` value, the `Content-Type` is set to `multipart/form-data` by the `FormHttpMessageConverter`.
|
||||
If the `MultiValueMap` has `String` values, the `Content-Type` defaults to `application/x-www-form-urlencoded`.
|
||||
If necessary the `Content-Type` may also be set explicitly.
|
||||
|
||||
[[rest-request-factories]]
|
||||
=== Client Request Factories
|
||||
|
||||
@@ -23,13 +23,16 @@ For all converters, a default media type is used, but you can override it by set
|
||||
By default, this converter supports all text media types(`text/{asterisk}`) and writes with a `Content-Type` of `text/plain`.
|
||||
|
||||
| `FormHttpMessageConverter`
|
||||
| An `HttpMessageConverter` implementation that can read and write form data from the HTTP request and response.
|
||||
| An `HttpMessageConverter` implementation that can read and write URL encoded forms.
|
||||
By default, this converter reads and writes the `application/x-www-form-urlencoded` media type.
|
||||
Form data is read from and written into a `MultiValueMap<String, String>`.
|
||||
The converter can also write (but not read) multipart data read from a `MultiValueMap<String, Object>`.
|
||||
By default, `multipart/form-data` is supported.
|
||||
Additional multipart subtypes can be supported for writing form data.
|
||||
Consult the javadoc for `FormHttpMessageConverter` for further details.
|
||||
|
||||
| `MultipartHttpMessageConverter`
|
||||
| An `HttpMessageConverter` implementation that can read and write multipart messages.
|
||||
`MultiValueMap<String, Object>` can be written to multipart messages, converting each part independently using
|
||||
the configured message converters. Multipart messages can be read into `MultiValueMap<String, Part>`, each value
|
||||
being a `Part` or one of its subtypes (`FormFieldPart` and `FilePart`).
|
||||
By default, `multipart/form-data` is supported. Additional multipart subtypes can be supported for writing form data.
|
||||
|
||||
| `ByteArrayHttpMessageConverter`
|
||||
| An `HttpMessageConverter` implementation that can read and write byte arrays from the HTTP request and response.
|
||||
|
||||
Reference in New Issue
Block a user