Skip to main content
Advertisement

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

  1. Duplicate Filenames: Using the original filename directly can lead to overwriting existing files. It is safer to generate unique filenames using tools like UUID.
  2. 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.
  3. Storage Choice: While saving to a local directory is fine initially, scaling a service usually requires switching to dedicated cloud storage like ** AWS S3**.


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();
}
}

tip

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.

Advertisement