3.6 Handling File Uploads (MultipartFile)
Learn how to handle image or document uploads in web applications using the MultipartFile interface and its related configurations.
1. How File Uploads Work (multipart/form-data)
Files are large binary data, not simple text. Therefore, they cannot be efficiently sent using application/json. For this purpose, HTTP uses a special encoding called multipart/form-data. In Spring, we receive this data using the MultipartFile interface.
2. File Upload Implementation Example
Controller Implementation
@RestController
@Slf4j
public class FileUploadController {
@PostMapping("/api/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
if (file.isEmpty()) {
return "File is empty.";
}
log.info("Filename: {}", file.getOriginalFilename());
log.info("File Size: {} bytes", file.getSize());
log.info("Content Type: {}", file.getContentType());
// Example: Saving to a local directory
String fullPath = "/uploads/" + file.getOriginalFilename();
file.transferTo(new File(fullPath));
return "Upload Success: " + fullPath;
}
}
3. Upload Capacity Configuration (application.yml)
Spring Boot has small default limits for file uploads. To allow large files, add the following to your application.yml:
spring:
servlet:
multipart:
max-file-size: 10MB # Max size for a single file
max-request-size: 50MB # Max total size for a single HTTP request
4. Practical Considerations
- Duplicate Filenames: Using the original filename directly can lead to overwriting existing files. It is safer to generate unique filenames using tools like
UUID. - Security: If an uploaded file is an executable script (.php, .sh, etc.), the server could be compromised. Always validate file extensions and perform security checks.
- Storage Choice: While saving to a local directory is fine initially, scaling a service usually requires switching to dedicated cloud storage like ** AWS S3**.
sidebar_position: 9
3.9 API Documentation with OpenAPI (Swagger)
For REST APIs, keeping request/response specs in sync with code and letting front-end or external developers try endpoints is standard practice. OpenAPI 3 (formerly Swagger) with Spring Boot lets you auto-generate API docs from your controllers.
Reference: Spring Boot 3.2.x, springdoc-openapi-starter-webmvc-ui
1. Why Automate API Docs?
- Manual docs: Drift from the real API and easy to miss updates.
- Generated docs: Built from controllers, DTOs, and annotations so the code is the source of truth.
- Swagger UI: Browse and call APIs from the browser for quick testing.
2. Add springdoc-openapi
For Spring Boot 3, use springdoc-openapi. (springfox does not support Boot 3.)
dependencies {
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
}
After starting the app you can use:
- Swagger UI:
http://localhost:8080/swagger-ui.html - OpenAPI JSON:
http://localhost:8080/v3/api-docs
3. Basic application.yml
springdoc:
api-docs:
path: /v3/api-docs
swagger-ui:
path: /swagger-ui.html
operationsSorter: method
tagsSorter: alpha
4. Global API Info and Tags
Use OpenAPI bean to set title, version, and description.
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.info(new Info()
.title("My REST API")
.version("1.0")
.description("API specification"));
}
}
5. Describe Controllers and DTOs
Use @Operation, @Parameter, and @Schema to improve the generated docs.
@RestController
@RequestMapping("/api/users")
@Tag(name = "User API", description = "User management APIs")
public class UserController {
@Operation(summary = "Get user by ID", description = "Returns a single user by ID.")
@Parameter(name = "id", description = "User ID", required = true)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Success"),
@ApiResponse(responseCode = "404", description = "User not found")
})
@GetMapping("/{id}")
public ResponseEntity<ApiResponse<UserResponseDto>> getUser(@PathVariable Long id) {
// ...
}
}
@Schema(description = "User response DTO")
public record UserResponseDto(
@Schema(description = "User ID") Long id,
@Schema(description = "Email") String email,
@Schema(description = "Name") String name
) {}
6. With Spring Security
Often Swagger UI and api-docs are allowed without authentication, or only in development.
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
}
In production, align API versioning (e.g. /api/v1/) with your OpenAPI spec and use the generated v3/api-docs in CI for contract tests or client code generation.