skip to content

How do you receive an uploaded file in a Spring WebFlux controller?

level: juniorimportance: must knowfreq 70%

answer

  1. @RequestPart FilePart
  2. transferTo(Path) -> Mono<Void>
  3. FilePart extends Part
  4. multipart/form-data
  5. never blocking Files.copy

basics

~10 s

Bind 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 s

In 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
java
@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

for a junior

Know @RequestPart FilePart and transferTo return a Mono.

for a middle

Distinguish FilePart vs FormFieldPart and know the org.springframework.http.codec.multipart package, not Servlet MultipartFile.

for a senior

Explain why transferTo is non-blocking and buffer-safe versus blocking IO.

for a principal

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

context