skip to content

How does Spring detect and parse multipart requests, and what is StandardServletMultipartResolver?

level: middleimportance: should knowfreq 35%

answer

  1. DispatcherServlet.isMultipart -> wrap request
  2. bean name must be 'multipartResolver'
  3. StandardServletMultipartResolver delegates to container getParts()
  4. MultipartAutoConfiguration + MultipartConfigElement
  5. CommonsMultipartResolver removed in Spring 6

basics

~10 s

The DispatcherServlet asks a MultipartResolver bean (named multipartResolver) whether the request is multipart; if so it wraps it as a MultipartHttpServletRequest. Spring Boot auto-configures StandardServletMultipartResolver, which delegates parsing to the Servlet container.

solid answer

~40 s

On each request, DispatcherServlet calls MultipartResolver.isMultipart(); if true it wraps the request in a MultipartHttpServletRequest so parts become MultipartFiles. Spring Boot auto-registers a bean named multipartResolver of type StandardServletMultipartResolver, which relies on the Servlet 3.0+ container's own multipart parsing (HttpServletRequest.getParts()) — no third-party library. It's configured through a MultipartConfigElement derived from spring.servlet.multipart.* properties (max sizes, temp location, file-size-threshold, resolve-lazily). The older CommonsMultipartResolver (Apache Commons FileUpload) existed for pre-Servlet-3.0 containers but was removed in Spring Framework 6. Because parsing is container-driven, size limits are enforced by the container and exceeding them raises MaxUploadSizeExceededException. You rarely define the resolver yourself; you just set properties.

code

java · 26 lines
java
// Typical Spring Boot: no bean needed — just properties (application.yml):
//   spring.servlet.multipart:
//     max-file-size: 20MB
//     max-request-size: 25MB
//     file-size-threshold: 2KB
//     location: /var/app/tmp
//     resolve-lazily: false

// Only if you must customize beyond properties (bean name is mandatory):
@Configuration
public class MultipartConfig {

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory f = new MultipartConfigFactory();
        f.setMaxFileSize(DataSize.ofMegabytes(20));
        f.setMaxRequestSize(DataSize.ofMegabytes(25));
        f.setLocation("/var/app/tmp");
        return f.createMultipartConfig();
    }

    @Bean(name = "multipartResolver") // name is required for DispatcherServlet lookup
    public StandardServletMultipartResolver multipartResolver() {
        return new StandardServletMultipartResolver();
    }
}

go deeper

for a junior

Know Spring Boot auto-configures multipart; you just set properties.

for a middle

Explain the DispatcherServlet resolver lookup, StandardServletMultipartResolver delegating to the container, and the mandatory bean name.

for a senior

Discuss MultipartConfigElement, container-level limits interacting with Spring's, and resolve-lazily semantics.

for a principal

Reason about parsing position relative to filters/security, container portability, and when a custom resolver is justified.

## The dispatch flow 1. A request reaches **`DispatcherServlet`**. 2. `DispatcherServlet.checkMultipart(request)` calls the injected **`MultipartResolver.isMultipart(request)`** (true when `Content-Type` starts with `multipart/`). 3. If multipart, the resolver wraps the request in a **`MultipartHttpServletRequest`** (a subinterface of `HttpServletRequest`) so handler-argument resolvers can expose parts as **`MultipartFile`**. 4. After the request completes, `DispatcherServlet` calls `cleanupMultipart(...)` to release temp resources (for the standard resolver, the container manages this). ## `StandardServletMultipartResolver` - Implementation of `MultipartResolver` that delegates to the **Servlet 3.0+ container's native multipart support** — it calls `HttpServletRequest.getParts()` / `getPart(name)`. No Apache Commons dependency. - Requires the servlet to have multipart config (a `MultipartConfigElement`, equivalent to `@MultipartConfig`). Spring Boot wires this automatically from `MultipartProperties`. - **Bean name matters**: `DispatcherServlet` looks up the resolver by the fixed bean name **`multipartResolver`**. A custom resolver must use that name to be picked up. ## Spring Boot auto-configuration `MultipartAutoConfiguration` (active when `spring.servlet.multipart.enabled=true`, the default) registers: - a `MultipartConfigElement` built from `spring.servlet.multipart.*`, and - a `StandardServletMultipartResolver` bean named `multipartResolver`. So in a typical Boot app you configure behavior purely via properties; you don't declare beans. ### Key properties (`spring.servlet.multipart.*`) - `enabled` (default `true`) — turn multipart handling on/off. - `max-file-size` (default `1MB`) — per-file cap. - `max-request-size` (default `10MB`) — whole-request cap. - `file-size-threshold` (default `0B`) — above this, the container spools the part to disk; `0` means always to disk. - `location` — temp directory for spooled files (defaults to the container temp dir). - `resolve-lazily` (default `false`) — when `true`, parsing is deferred until a part is first accessed instead of eagerly at request time. ## Legacy: `CommonsMultipartResolver` - Based on **Apache Commons FileUpload**; historically used to support **pre-Servlet-3.0** containers or to override parsing behavior. - **Removed in Spring Framework 6 (Spring Boot 3+).** On modern stacks, `StandardServletMultipartResolver` is the only built-in option. ## Gotchas - If you register a custom `MultipartResolver` bean but name it anything other than `multipartResolver`, `DispatcherServlet` won't use it. - With `StandardServletMultipartResolver`, the **container** enforces limits, so container-specific settings (e.g., Tomcat `maxSwallowSize`, `maxPostSize`) can also affect uploads independently of Spring properties. - `resolve-lazily=false` (default) means the whole multipart body is parsed before your handler runs; a payload exceeding limits fails early with `MaxUploadSizeExceededException`. - Multipart parsing happens **before** most filters that read the body; frameworks like Spring Security must see the multipart request correctly (usually fine, but body-reading filters can consume the stream). ## When to touch it Almost never define the resolver manually. Tune sizes/temp location via properties; only drop to a custom `MultipartConfigElement`/bean for unusual container or parsing needs.

  • You defined a MultipartResolver bean but uploads still fail — what's a likely cause?
    DispatcherServlet resolves the resolver by the fixed bean name 'multipartResolver'. If your bean has a different name, it's ignored and the auto-configured (or no) resolver is used. Rename the bean or rely on Boot's auto-config.
  • What replaced CommonsMultipartResolver and why?
    StandardServletMultipartResolver, which uses the Servlet 3.0+ container's native multipart parsing. Commons FileUpload-based CommonsMultipartResolver was removed in Spring Framework 6 since modern containers all support multipart natively.

saying these in an interview costs you the question

  • Saying you must always add Apache Commons FileUpload for uploads (not on Servlet 3.0+/Spring 6).
  • Registering a resolver bean under a non-'multipartResolver' name and expecting it to work.
  • Claiming Spring parses multipart itself rather than delegating to the container (for the standard resolver).
  • Thinking multipart handling is off by default (it's enabled).

context