How do you receive an uploaded file in a Spring WebFlux controller?
answer
- @RequestPart FilePart
- transferTo(Path) -> Mono<Void>
- FilePart extends Part
- multipart/form-data
- never blocking Files.copy
basics
~10 sBind the named multipart part with @RequestPart to a FilePart parameter. FilePart exposes filename(), headers(), and transferTo(path) to save the upload. Return a Mono/Flux so the handler stays non-blocking.
solid answer
~30 sIn WebFlux a multipart request is decoded into Part objects. To grab one uploaded file you use @RequestPart("file") FilePart file — FilePart extends Part and adds filename() and transferTo(Path). You typically call file.transferTo(path) which returns Mono<Void> and streams the bytes to disk without blocking. The handler returns a reactive type (Mono<Void>, Mono<ResponseEntity>) so nothing blocks. @RequestPart binds a single named part; for form-field text parts you'd get a FormFieldPart with value(). Content type must be multipart/form-data. Never call blocking IO (e.g. Files.copy on an InputStream) — use transferTo or DataBufferUtils so the upload stays fully reactive and backpressure-aware.
code
java · 11 lines@RestController
class UploadController {
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
Mono<ResponseEntity<String>> upload(@RequestPart("file") FilePart file) {
Path target = Path.of("/tmp/uploads", file.filename());
// transferTo streams DataBuffers to disk and releases them; non-blocking
return file.transferTo(target)
.thenReturn(ResponseEntity.ok("saved " + file.filename()));
}
}go deeper
Know @RequestPart FilePart and transferTo return a Mono.
Distinguish FilePart vs FormFieldPart and know the org.springframework.http.codec.multipart package, not Servlet MultipartFile.
Explain why transferTo is non-blocking and buffer-safe versus blocking IO.
Frame the choice of binding type against streaming vs buffering and thread-model implications.
**Multipart in WebFlux.** When a browser or client posts `multipart/form-data`, the body is a sequence of *parts*, each with its own headers (name, filename, content-type) and a body. Spring WebFlux models each part with the interface `org.springframework.http.codec.multipart.Part`. Sub-interfaces: - `FilePart` — a part that is an uploaded file. Adds `String filename()` and `Mono<Void> transferTo(Path)` / `transferTo(File)`. - `FormFieldPart` — a simple text form field. Adds `String value()`. **Binding with @RequestPart.** `@RequestPart("file")` selects the part whose `name` equals `file` and binds it. Valid target types include: - `FilePart` / `Part` — the raw part. - `Mono<FilePart>` — deferred access. - A POJO — the part's content is decoded through the configured codecs (e.g. a JSON part into an object). **Saving the file.** The idiomatic, non-blocking way is: ```java return file.transferTo(Path.of("/uploads/" + file.filename())); ``` `transferTo` streams the part's `DataBuffer`s to the target and **releases** them for you, returning `Mono<Void>` that completes when the write finishes. Do **not** grab an InputStream and call blocking `Files.copy` — that blocks an event-loop thread and defeats the reactive model. **Gotchas for a junior:** - The request must be `multipart/form-data`; a plain body won't decode into parts. - The handler must return a reactive type; returning `void` and doing the work imperatively risks the response completing before the async write finishes. - `@RequestPart` is WebFlux/MVC shared, but the WebFlux `FilePart` lives in `org.springframework.http.codec.multipart`, not the Servlet `MultipartFile`. - `@RequestParam` is for query/form-field values, not files, in WebFlux. **When to use.** Single named file upload — `@RequestPart FilePart`. Multiple/unknown parts — `Flux<Part>` (sibling question). Fully streaming pass-through — `PartEvent` API.
- What is the difference between FilePart and FormFieldPart?Both extend Part. FilePart represents an uploaded file and adds filename() plus transferTo(); FormFieldPart represents a plain text form field and adds value(). You get FormFieldPart for non-file inputs in the same multipart body.
- Why prefer transferTo over reading an InputStream?transferTo streams the part's DataBuffers reactively to the target, returns a Mono<Void> that signals completion, and releases the buffers automatically. Reading an InputStream and using Files.copy blocks an event-loop thread, breaking the non-blocking contract.
saying these in an interview costs you the question
- Using Servlet MultipartFile in a WebFlux handler
- Calling blocking Files.copy on an InputStream from the part
- Returning void and doing the save imperatively so the response races the write
- Using @RequestParam to bind the file