A lightweight image upload and delivery API built with Spring Boot.
This service was created to centralize image handling for future projects. It provides a simple flow for uploading user profile pictures, processing them, storing them in a RustFS bucket, and retrieving them later through a download endpoint.
- Spring Boot — API framework
- RustFS — S3-compatible object storage
- ImageKit — image processing and optimization
- PostgreSQL — metadata storage
The service exposes two main endpoints:
POST /api/v1/upload/profile-picture?username={username}GET /api/v1/download/profile-picture/{username}
When a client uploads a profile picture:
- The API receives the file and the
username - The image is read from the multipart request
- A unique filename is generated using a UUID
- The image is processed (resize, crop, face focus, etc.)
- The processed image is stored in RustFS
- The database is updated with the storage key
- A download URL is returned
If a profile picture already exists, the old image is deleted before saving the new one.
When a client requests a profile picture:
- The API looks up the username in the database
- Retrieves the storage key
- Fetches the image from RustFS
- Returns the image as
image/jpeg
If not found → 404 Not Found
POST /api/v1/upload/profile-picture?username={username}
Request
- Content-Type:
multipart/form-data - Query param:
username - Form-data:
file→ image file
Example
curl -X POST "http://localhost:8088/api/v1/upload/profile-picture?username=john" \
-F "file=@profile.jpg"Response
{
"downloadUrl": "http://localhost:8088/api/v1/download/profile-picture/john",
"message": "Uploaded successfully"
}GET /api/v1/download/profile-picture/{username}
Example
curl -L "http://localhost:8088/api/v1/download/profile-picture/john" --output profile.jpgThe application is configured via environment variables.
RUSTFS_BASE_URLRUSTFS_ACCESS_KEYRUSTFS_SECRET_KEYRUSTFS_BUCKET
IMAGEKIT_PUBLIC_KEYIMAGEKIT_PRIVATE_KEYIMAGEKIT_URL_ENDPOINT
DB_URLDB_USERNAMEDB_PASSWORD
SERVER_PORT(default:8088)
1. Start dependencies (PostgreSQL)
docker compose up -d2. Run the application
./mvnw spring-boot:runGET /api/actuator/health
features/
├── upload/
│ ├── controller/
│ ├── service/
│ └── repository/
├── download/
│ ├── controller/
│ └── service/
└── imagekit/
└── strategy/
- Each user has one profile picture
- Upload replaces the previous image
- Old images are automatically deleted from storage
Package name was changed from:
ao.vanadio.image-processor-service
to:
ao.vanadio.image_processor_service
due to Java naming constraints.
This service is designed to be reusable across multiple projects, providing a clean and scalable way to handle image uploads and delivery.