Careeroza
Uploading Files
MultipartFile
Browsers and apps send files as multipart/form-data. Spring gives each file to your controller as a MultipartFile.
@RestController
@RequestMapping("/api/products/{id}/images")
@RequiredArgsConstructor
public class ProductImageController {
private final ImageStorageService storage;
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<ImageResponse> upload(@PathVariable Long id,
@RequestParam("file") MultipartFile file) {
ImageResponse saved = storage.store(id, file);
return ResponseEntity.created(URI.create(saved.url())).body(saved);
}
@PostMapping(path = "/bulk", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public List<ImageResponse> uploadMany(@PathVariable Long id,
@RequestParam("files") List<MultipartFile> files) {
return files.stream().map(f -> storage.store(id, f)).toList();
}
}Size Limits
Example
The defaults are 1 MB per file and 10 MB per request. Set your own:
application.yml
spring:
servlet:
multipart:
max-file-size: 5MB
max-request-size: 20MBExample
Upload with curl (-F sends multipart form data):
curl -i -F "[email protected]" localhost:8080/api/products/3/imagesExample output
HTTP/1.1 201 Created
Location: /api/files/products/3/9b2f4c1e.jpg
Content-Type: application/json
{"fileName":"9b2f4c1e.jpg","originalName":"pixel9-front.jpg","size":348211,"contentType":"image/jpeg","url":"/api/files/products/3/9b2f4c1e.jpg"}Note: A too-large file throws MaxUploadSizeExceededException. Handle it in your @RestControllerAdvice and return 413 Payload Too Large.
Uploading from React
async function uploadImage(productId, file) {
const form = new FormData();
form.append('file', file); // do NOT set Content-Type yourself
const res = await fetch(`/api/products/${productId}/images`, { method: 'POST', body: form });
if (!res.ok) throw new Error('Upload failed: ' + res.status);
return res.json();
}
<input type="file" accept="image/png,image/jpeg,image/webp"
onChange={e => uploadImage(3, e.target.files[0])} />