Skip to content

Commit f6ea740

Browse files
committed
Improve docs on client-side multipart requests
Issue: SPR-16635
1 parent d007c25 commit f6ea740

File tree

2 files changed

+69
-10
lines changed

2 files changed

+69
-10
lines changed

src/docs/asciidoc/integration.adoc

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,44 @@ to serialize only a subset of the object properties. For example:
12471247
ResponseEntity<String> response = template.exchange(requestEntity, String.class);
12481248
----
12491249

1250+
[[rest-template-multipart]]
1251+
===== Multipart
1252+
1253+
To send multipart data, you need to provide a `MultiValueMap<String, ?>` whose values are
1254+
either Objects representing part content, or `HttpEntity` representing the content and
1255+
headers for a part. `MultipartBodyBuilder` provides a convenient API to prepare a
1256+
multipart request:
1257+
1258+
[source,java,intent=0]
1259+
[subs="verbatim,quotes"]
1260+
----
1261+
MultipartBodyBuilder builder = new MultipartBodyBuilder();
1262+
builder.part("fieldPart", "fieldValue");
1263+
builder.part("filePart", new FileSystemResource("...logo.png"));
1264+
builder.part("jsonPart", new Person("Jason"));
1265+
1266+
MultiValueMap<String, HttpEntity<?>> parts = builder.build();
1267+
----
1268+
1269+
In most cases you do not have to specify the `Content-Type` for each part. The content
1270+
type is determined automatically based on the `HttpMessageConverter` chosen to serialize it,
1271+
or in the case of a `Resource` based on the file extension. If necessary you can
1272+
explicitly provide the `MediaType` to use for each part through one fo the overloaded
1273+
builder `part` methods.
1274+
1275+
Once the `MultiValueMap` is ready, you can pass it to the `RestTemplate`:
1276+
1277+
[source,java,intent=0]
1278+
[subs="verbatim,quotes"]
1279+
----
1280+
MultipartBodyBuilder builder = ...;
1281+
template.postForObject("http://example.com/upload", builder.build(), Void.class);
1282+
----
1283+
1284+
If the `MultiValueMap` contains at least one non-String value, which could also be
1285+
represent regular form data (i.e. "application/x-www-form-urlencoded"), you don't have to
1286+
set the `Content-Type` to "multipart/form-data". This is always the case when using
1287+
`MultipartBodyBuilder` which ensures an `HttpEntity` wrapper.
12501288

12511289

12521290
[[rest-async-resttemplate]]

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

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ By comparison to the <<integration.adoc#rest-resttemplate,RestTemplate>>, the
2222
* supports both synchronous and asynchronous scenarios.
2323
* supports streaming up or down from a server.
2424

25-
For most concurrent scenarios, e.g. a sequence of possibly inter-dependent HTTP calls,
26-
or for making remote calls from the server-side, prefer using the `WebClient`.
25+
The `RestTemplate` is not a good fit for use in non-blocking applications, and therefore
26+
Spring WebFlux application should always use the `WebClient`. The `WebClient` should also
27+
be preferred in Spring MVC, in most high concurrency scenarios, and for composing a
28+
sequence of remote, inter-dependent calls.
2729

2830

2931

@@ -201,9 +203,10 @@ You can also supply form data in-line via `BodyInserters`:
201203
[[webflux-client-body-multipart]]
202204
=== Multipart data
203205

204-
To send multipart data, provide a `MultiValueMap<String, ?>` where values are either an
205-
Object representing the part body, or an `HttpEntity` representing the part body and
206-
headers. `MultipartBodyBuilder` can be used to build the parts:
206+
To send multipart data, you need to provide a `MultiValueMap<String, ?>` whose values are
207+
either Objects representing part content, or `HttpEntity` representing the content and
208+
headers for a part. `MultipartBodyBuilder` provides a convenient API to prepare a
209+
multipart request:
207210

208211
[source,java,intent=0]
209212
[subs="verbatim,quotes"]
@@ -214,19 +217,36 @@ headers. `MultipartBodyBuilder` can be used to build the parts:
214217
builder.part("jsonPart", new Person("Jason"));
215218
216219
MultiValueMap<String, HttpEntity<?>> parts = builder.build();
220+
----
221+
222+
In most cases you do not have to specify the `Content-Type` for each part. The content
223+
type is determined automatically based on the `HttpMessageWriter` chosen to serialize it,
224+
or in the case of a `Resource` based on the file extension. If necessary you can
225+
explicitly provide the `MediaType` to use for each part through one fo the overloaded
226+
builder `part` methods.
227+
228+
Once a `MultiValueMap` is prepared, the easiest way to pass it to the the `WebClient` is
229+
through the `syncBody` method:
230+
231+
[source,java,intent=0]
232+
[subs="verbatim,quotes"]
233+
----
234+
MultipartBodyBuilder builder = ...;
217235
218236
Mono<Void> result = client.post()
219237
.uri("/path", id)
220-
.syncBody(parts)
238+
.syncBody(**builder.build()**)
221239
.retrieve()
222240
.bodyToMono(Void.class);
223241
----
224242

225-
Note that the content type for each part is automatically set based on the extension of the
226-
file being written or the type of Object. If you prefer you can also be more explicit and
227-
specify the content type for each part.
243+
If the `MultiValueMap` contains at least one non-String value, which could also be
244+
represent regular form data (i.e. "application/x-www-form-urlencoded"), you don't have to
245+
set the `Content-Type` to "multipart/form-data". This is always the case when using
246+
`MultipartBodyBuilder` which ensures an `HttpEntity` wrapper.
228247

229-
You can also supply multipart data in-line via `BodyInserters`:
248+
As an alternative to `MultipartBodyBuilder`, you can also provide multipart content,
249+
inline-style, through the built-in `BodyInserters`. For example:
230250

231251
[source,java,intent=0]
232252
[subs="verbatim,quotes"]
@@ -242,6 +262,7 @@ You can also supply multipart data in-line via `BodyInserters`:
242262

243263

244264

265+
245266
[[webflux-client-builder]]
246267
== Builder options
247268

0 commit comments

Comments
 (0)