Browse Source

Improve docs on client-side multipart requests

Issue: SPR-16635
pull/1737/merge
Rossen Stoyanchev 8 years ago
parent
commit
f6ea7407e6
  1. 38
      src/docs/asciidoc/integration.adoc
  2. 41
      src/docs/asciidoc/web/webflux-webclient.adoc

38
src/docs/asciidoc/integration.adoc

@ -1247,6 +1247,44 @@ to serialize only a subset of the object properties. For example:
ResponseEntity<String> response = template.exchange(requestEntity, String.class); ResponseEntity<String> response = template.exchange(requestEntity, String.class);
---- ----
[[rest-template-multipart]]
===== Multipart
To send multipart data, you need to provide a `MultiValueMap<String, ?>` whose values are
either Objects representing part content, or `HttpEntity` representing the content and
headers for a part. `MultipartBodyBuilder` provides a convenient API to prepare a
multipart request:
[source,java,intent=0]
[subs="verbatim,quotes"]
----
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("fieldPart", "fieldValue");
builder.part("filePart", new FileSystemResource("...logo.png"));
builder.part("jsonPart", new Person("Jason"));
MultiValueMap<String, HttpEntity<?>> parts = builder.build();
----
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` to use for each part through one fo the overloaded
builder `part` methods.
Once the `MultiValueMap` is ready, you can pass it to the `RestTemplate`:
[source,java,intent=0]
[subs="verbatim,quotes"]
----
MultipartBodyBuilder builder = ...;
template.postForObject("http://example.com/upload", builder.build(), Void.class);
----
If the `MultiValueMap` contains at least one non-String value, which could also be
represent regular form data (i.e. "application/x-www-form-urlencoded"), you don't have to
set the `Content-Type` to "multipart/form-data". This is always the case when using
`MultipartBodyBuilder` which ensures an `HttpEntity` wrapper.
[[rest-async-resttemplate]] [[rest-async-resttemplate]]

41
src/docs/asciidoc/web/webflux-webclient.adoc

@ -22,8 +22,10 @@ By comparison to the <<integration.adoc#rest-resttemplate,RestTemplate>>, the
* supports both synchronous and asynchronous scenarios. * supports both synchronous and asynchronous scenarios.
* supports streaming up or down from a server. * supports streaming up or down from a server.
For most concurrent scenarios, e.g. a sequence of possibly inter-dependent HTTP calls, The `RestTemplate` is not a good fit for use in non-blocking applications, and therefore
or for making remote calls from the server-side, prefer using the `WebClient`. Spring WebFlux application should always use the `WebClient`. The `WebClient` should also
be preferred in Spring MVC, in most high concurrency scenarios, and for composing a
sequence of remote, inter-dependent calls.
@ -201,9 +203,10 @@ You can also supply form data in-line via `BodyInserters`:
[[webflux-client-body-multipart]] [[webflux-client-body-multipart]]
=== Multipart data === Multipart data
To send multipart data, provide a `MultiValueMap<String, ?>` where values are either an To send multipart data, you need to provide a `MultiValueMap<String, ?>` whose values are
Object representing the part body, or an `HttpEntity` representing the part body and either Objects representing part content, or `HttpEntity` representing the content and
headers. `MultipartBodyBuilder` can be used to build the parts: headers for a part. `MultipartBodyBuilder` provides a convenient API to prepare a
multipart request:
[source,java,intent=0] [source,java,intent=0]
[subs="verbatim,quotes"] [subs="verbatim,quotes"]
@ -214,19 +217,36 @@ headers. `MultipartBodyBuilder` can be used to build the parts:
builder.part("jsonPart", new Person("Jason")); builder.part("jsonPart", new Person("Jason"));
MultiValueMap<String, HttpEntity<?>> parts = builder.build(); MultiValueMap<String, HttpEntity<?>> parts = builder.build();
----
In most cases you do not have to specify the `Content-Type` for each part. The content
type is determined automatically based on the `HttpMessageWriter` chosen to serialize it,
or in the case of a `Resource` based on the file extension. If necessary you can
explicitly provide the `MediaType` to use for each part through one fo the overloaded
builder `part` methods.
Once a `MultiValueMap` is prepared, the easiest way to pass it to the the `WebClient` is
through the `syncBody` method:
[source,java,intent=0]
[subs="verbatim,quotes"]
----
MultipartBodyBuilder builder = ...;
Mono<Void> result = client.post() Mono<Void> result = client.post()
.uri("/path", id) .uri("/path", id)
.syncBody(parts) .syncBody(**builder.build()**)
.retrieve() .retrieve()
.bodyToMono(Void.class); .bodyToMono(Void.class);
---- ----
Note that the content type for each part is automatically set based on the extension of the If the `MultiValueMap` contains at least one non-String value, which could also be
file being written or the type of Object. If you prefer you can also be more explicit and represent regular form data (i.e. "application/x-www-form-urlencoded"), you don't have to
specify the content type for each part. set the `Content-Type` to "multipart/form-data". This is always the case when using
`MultipartBodyBuilder` which ensures an `HttpEntity` wrapper.
You can also supply multipart data in-line via `BodyInserters`: As an alternative to `MultipartBodyBuilder`, you can also provide multipart content,
inline-style, through the built-in `BodyInserters`. For example:
[source,java,intent=0] [source,java,intent=0]
[subs="verbatim,quotes"] [subs="verbatim,quotes"]
@ -242,6 +262,7 @@ You can also supply multipart data in-line via `BodyInserters`:
[[webflux-client-builder]] [[webflux-client-builder]]
== Builder options == Builder options

Loading…
Cancel
Save