Spring Boot
MultipartFile
@RequestParam
File Upload
Java Development

Using RequestParam for multipartfile is a right way?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Yes, using @RequestParam for MultipartFile is the standard and correct approach in Spring Boot for handling file uploads. The annotation binds a multipart form field to a MultipartFile parameter in your controller method. For more complex scenarios with additional metadata, use @RequestPart instead. Both annotations work with multipart/form-data requests and are fully supported by Spring's multipart resolver.

Basic File Upload with @RequestParam

java
1@RestController
2@RequestMapping("/api/files")
3public class FileUploadController {
4
5    @PostMapping("/upload")
6    public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
7        if (file.isEmpty()) {
8            return ResponseEntity.badRequest().body("File is empty");
9        }
10
11        String filename = file.getOriginalFilename();
12        long size = file.getSize();
13        String contentType = file.getContentType();
14
15        // Save to disk
16        Path destination = Path.of("/uploads", filename);
17        file.transferTo(destination);
18
19        return ResponseEntity.ok("Uploaded: " + filename + " (" + size + " bytes)");
20    }
21}

The client sends a multipart/form-data request with a form field named "file".

cURL Test

bash
curl -X POST http://localhost:8080/api/files/upload \
  -F "file=@/path/to/document.pdf"

Multiple File Upload

java
1@PostMapping("/upload-multiple")
2public ResponseEntity<String> uploadMultiple(
3        @RequestParam("files") List<MultipartFile> files) {
4
5    for (MultipartFile file : files) {
6        if (!file.isEmpty()) {
7            file.transferTo(Path.of("/uploads", file.getOriginalFilename()));
8        }
9    }
10
11    return ResponseEntity.ok("Uploaded " + files.size() + " files");
12}
bash
curl -X POST http://localhost:8080/api/files/upload-multiple \
  -F "[email protected]" \
  -F "[email protected]"

File Upload with Additional Form Data

java
1@PostMapping("/upload-with-metadata")
2public ResponseEntity<String> uploadWithMetadata(
3        @RequestParam("file") MultipartFile file,
4        @RequestParam("description") String description,
5        @RequestParam(value = "category", defaultValue = "general") String category) {
6
7    // file, description, and category are all extracted from the multipart form
8    return ResponseEntity.ok(
9        "File: " + file.getOriginalFilename() +
10        ", Description: " + description +
11        ", Category: " + category
12    );
13}
bash
1curl -X POST http://localhost:8080/api/files/upload-with-metadata \
2  -F "[email protected]" \
3  -F "description=Annual report" \
4  -F "category=reports"

@RequestParam vs @RequestPart

java
1// @RequestParam: simple file + string fields
2@PostMapping("/simple")
3public void simple(
4    @RequestParam("file") MultipartFile file,
5    @RequestParam("name") String name) { }
6
7// @RequestPart: file + JSON body parts (with content type)
8@PostMapping("/complex")
9public void complex(
10    @RequestPart("file") MultipartFile file,
11    @RequestPart("metadata") FileMetadata metadata) { }
12// FileMetadata is deserialized from JSON automatically

@RequestPart uses the Content-Type header of each part for deserialization. Use it when sending JSON alongside files:

bash
curl -X POST http://localhost:8080/api/files/complex \
  -F "[email protected]" \
  -F "metadata={\"title\":\"Report\",\"year\":2025};type=application/json"

File Size Configuration

yaml
1# application.yml
2spring:
3  servlet:
4    multipart:
5      max-file-size: 10MB          # Max single file size
6      max-request-size: 50MB       # Max total request size
7      enabled: true                 # Enable multipart (default: true)
8      file-size-threshold: 2KB     # Threshold to write to disk vs memory
properties
# application.properties
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=50MB

File Validation

java
1@PostMapping("/upload")
2public ResponseEntity<String> upload(@RequestParam("file") MultipartFile file) {
3    // Check file is not empty
4    if (file.isEmpty()) {
5        return ResponseEntity.badRequest().body("File is empty");
6    }
7
8    // Validate file size (programmatic check)
9    if (file.getSize() > 5 * 1024 * 1024) {  // 5MB
10        return ResponseEntity.badRequest().body("File too large");
11    }
12
13    // Validate content type
14    String contentType = file.getContentType();
15    List<String> allowedTypes = List.of("image/jpeg", "image/png", "application/pdf");
16    if (!allowedTypes.contains(contentType)) {
17        return ResponseEntity.badRequest().body("Invalid file type: " + contentType);
18    }
19
20    // Validate file extension
21    String filename = file.getOriginalFilename();
22    if (filename != null && !filename.matches(".*\\.(jpg|jpeg|png|pdf)$")) {
23        return ResponseEntity.badRequest().body("Invalid file extension");
24    }
25
26    file.transferTo(Path.of("/uploads", filename));
27    return ResponseEntity.ok("Uploaded successfully");
28}

Saving to Different Locations

java
1// Save to disk
2file.transferTo(Path.of("/uploads", file.getOriginalFilename()));
3
4// Read as byte array (for database storage)
5byte[] bytes = file.getBytes();
6
7// Read as InputStream (for streaming to cloud storage)
8try (InputStream inputStream = file.getInputStream()) {
9    // Upload to S3, GCS, Azure Blob, etc.
10    s3Client.putObject(bucket, key, inputStream, metadata);
11}

Exception Handling

java
1@ControllerAdvice
2public class FileUploadExceptionHandler {
3
4    @ExceptionHandler(MaxUploadSizeExceededException.class)
5    public ResponseEntity<String> handleMaxSizeException(MaxUploadSizeExceededException ex) {
6        return ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE)
7            .body("File size exceeds the maximum allowed size");
8    }
9
10    @ExceptionHandler(MultipartException.class)
11    public ResponseEntity<String> handleMultipartException(MultipartException ex) {
12        return ResponseEntity.badRequest()
13            .body("Invalid multipart request: " + ex.getMessage());
14    }
15}

Common Pitfalls

  • Missing multipart/form-data content type: The client must send the request with Content-Type: multipart/form-data. Sending JSON with a file field does not work — the file must be a multipart form part. Most HTTP clients (Postman, cURL with -F) set this automatically.
  • Parameter name mismatch: @RequestParam("file") must match the form field name exactly. If the client sends [email protected] but the annotation says @RequestParam("document"), Spring returns a 400 error with "Required request part 'document' is not present".
  • File size limit exceeded silently: The default max-file-size is 1MB. Large uploads fail with a MaxUploadSizeExceededException. Configure spring.servlet.multipart.max-file-size and max-request-size in application properties.
  • Using @RequestBody instead of @RequestParam: @RequestBody reads the entire request body as a single object (for JSON). For file uploads, use @RequestParam or @RequestPart. Using @RequestBody with MultipartFile causes a "Content type not supported" error.
  • Not sanitizing file names: file.getOriginalFilename() returns the client-provided filename, which may contain path traversal characters like ../. Always sanitize the filename before saving: Paths.get(filename).getFileName().toString().

Summary

  • @RequestParam("file") MultipartFile file is the standard approach for file uploads in Spring Boot
  • Use @RequestPart when combining files with JSON metadata in the same request
  • Configure max-file-size and max-request-size in application properties for large uploads
  • Validate file size, content type, and file extension before processing
  • Always sanitize getOriginalFilename() to prevent path traversal attacks
  • Handle MaxUploadSizeExceededException with a @ControllerAdvice for user-friendly error messages

Course illustration
Course illustration

All Rights Reserved.