5.1 KiB
VOTIANLT Realtime & Photo Upload API
This document describes how mobile/Flutter apps can interact with the backend via STOMP (WebSocket) and how to upload photos via HTTP POST (new flow).
1) STOMP Overview
- Connect to one of the WebSocket endpoints:
/ws(SockJS fallback supported)/websocket(native WebSocket)/stomp(native WebSocket, alternate path)
- Application destination prefix:
/app - Broker destinations:
- Broadcast:
/topic/... - User specific:
/user/queue/...
- Broadcast:
Examples:
- Send a generic message: send to
/app/message, receive on/topic/messages - Job updates: send to
/app/job/status, receive on/topic/job-updates - Device locations: send to
/app/device/location, receive on/topic/device-locations - Task updates (broadcast):
/topic/task-updates - Task specific topic:
/topic/tasks/{taskId}
2) Photo Task – New HTTP Upload Flow
In the future, photos for a PHOTO task must NOT be embedded in the STOMP message anymore. Instead, upload the photos via HTTP POST and only send the task-completion event via STOMP without large payloads.
Endpoint
- URL:
POST /api/tasks/{taskId}/photos - Purpose: Upload one or many photos for a task of type
PHOTO. - Path params:
taskId(required): The MongoDB ObjectId of the task.
- Auth: (same as your app uses today; if you have a session/cookie or token, include it accordingly)
- CORS: Enabled for
*by default on this controller.
Content Types (choose one)
- Multipart form data (recommended for binary images)
Content-Type: multipart/form-data- Fields:
files: one or multiple image files (repeat the field for multiple images)completedBy(optional): username/id of the completing usernote(optional): any note (currently stored on the task when you mark it as completed via STOMP)
Example (curl):
curl -X POST "http://localhost:8080/api/tasks/66f5c2f1a3b6e27a1a234567/photos" \
-H "Content-Type: multipart/form-data" \
-F "files=@/path/to/photo1.jpg" \
-F "files=@/path/to/photo2.jpg" \
-F "completedBy=driver01" \
-F "note=Anlieferung dokumentiert"
- JSON with base64 strings (kept for compatibility)
Content-Type: application/json- Body:
{
"completedBy": "driver01",
"note": "Anlieferung dokumentiert",
"photos": [
"<base64-of-image-1>",
"<base64-of-image-2>"
]
}
Example (curl):
curl -X POST "http://localhost:8080/api/tasks/66f5c2f1a3b6e27a1a234567/photos" \
-H "Content-Type: application/json" \
-d '{
"completedBy":"driver01",
"note":"Anlieferung dokumentiert",
"photos":["iVBORw0KGgo...","iVBORw0KGgo..."]
}'
Simple JSON endpoint (single photo per call)
- URL:
POST /api/photos - Content-Type:
application/json - Body:
{
"taskId": "66f5c2f1a3b6e27a1a234567",
"photo": "<base64-of-image>",
"completedBy": "driver01",
"note": "optional"
}
- Multiple photos: call this endpoint multiple times (one image per request).
Example (curl):
curl -X POST "http://localhost:8080/api/photos" \
-H "Content-Type: application/json" \
-d '{
"taskId":"66f5c2f1a3b6e27a1a234567",
"photo":"iVBORw0KGgo...",
"completedBy":"driver01",
"note":"Anlieferung dokumentiert"
}'
Response
Both content types return the same JSON structure on success:
{
"timestamp": "2025-09-13T21:27:00",
"type": "photoUploadAck",
"success": true,
"photoId": "66f5c400b1a1b05b1c123abc",
"photosCount": 2,
"taskId": "66f5c2f1a3b6e27a1a234567",
"jobId": "66f5c2f1a3b6e27a1a200000"
}
Error responses use HTTP status codes with:
{ "timestamp": "...", "type": "photoUploadAck", "success": false, "message": "..." }
Server-side side-effect (notification)
After a successful upload, a small event is broadcast to the specific task topic:
- Destination:
/topic/tasks/{taskId} - Payload:
{ "event": "photoUploaded", "taskId": "...", "jobId": "...", "photosCount": 2, "timestamp": "..." }
Use this to update UI (e.g., show that photos have arrived) without transferring large images via STOMP.
Limits
- Multipart limits (configurable in
application.properties):spring.servlet.multipart.max-file-size=32MBspring.servlet.multipart.max-request-size=64MB
- Tomcat limits adjusted accordingly.
If you need higher limits, we can raise these values.
3) Marking Task as Completed (STOMP)
Continue to mark a task as completed via STOMP without embedding images:
- Send to:
/app/task/photo/completed - Payload (no photos inside):
{ "taskId": "66f5c2f1a3b6e27a1a234567", "completedBy": "driver01", "note": "Anlieferung dokumentiert" }
- Broadcasts an update to
/topic/task-updatesand/topic/tasks/{taskId}.
4) Retrieval of Photos (optional)
Currently, the backend stores uploaded photos as base64 in the photos collection referencing the taskId and jobId. If you need a download/list endpoint, let us know—we can expose /api/tasks/{taskId}/photos (GET) to return metadata and/or images.
If anything is unclear or you need different formats (e.g., presigned URLs, chunked uploads), please reach out.