225 lines
4.7 KiB
Markdown
225 lines
4.7 KiB
Markdown
# JSON Media Integration Guide (Admin Panel)
|
|
|
|
This guide documents the new media integration pattern introduced in the backend:
|
|
|
|
- Upload binary file once through `POST /api/v1/files/upload`
|
|
- Use the returned URL/key in JSON request bodies for business endpoints
|
|
|
|
This replaces direct form-data usage in common admin flows (while legacy multipart compatibility still exists).
|
|
|
|
---
|
|
|
|
## 1) New General Media Upload Endpoint
|
|
|
|
### `POST /api/v1/files/upload`
|
|
|
|
**Auth:** Bearer token required
|
|
**Content-Type:** `multipart/form-data`
|
|
**Purpose:** Upload media and return reference data for subsequent JSON requests.
|
|
|
|
### Request fields
|
|
|
|
- `media_type` (required): `image` | `audio` | `video`
|
|
- `file` (required): binary file
|
|
- `title` (optional, video only): Vimeo video title
|
|
- `description` (optional, video only): Vimeo video description
|
|
|
|
### Storage behavior
|
|
|
|
- `media_type=image` -> MinIO
|
|
- `media_type=audio` -> MinIO
|
|
- `media_type=video` -> Vimeo
|
|
|
|
### Success response shape
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"status_code": 200,
|
|
"message": "File uploaded successfully",
|
|
"data": {
|
|
"object_key": "image/abc123.webp",
|
|
"url": "https://...",
|
|
"content_type": "image/webp",
|
|
"media_type": "image",
|
|
"provider": "MINIO"
|
|
}
|
|
}
|
|
```
|
|
|
|
For videos, response includes Vimeo references:
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"status_code": 200,
|
|
"message": "Video uploaded successfully",
|
|
"data": {
|
|
"url": "https://vimeo.com/123456789",
|
|
"content_type": "video/mp4",
|
|
"media_type": "video",
|
|
"provider": "VIMEO",
|
|
"vimeo_id": "123456789",
|
|
"embed_url": "https://player.vimeo.com/video/123456789"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 2) Endpoints Updated to JSON Media Reference Flow
|
|
|
|
These endpoints now support JSON request bodies for media references.
|
|
|
|
## A) Profile Picture
|
|
|
|
### `POST /api/v1/user/:id/profile-picture`
|
|
|
|
**Old style:** multipart with `file`
|
|
**New style:** JSON with uploaded URL
|
|
|
|
#### JSON request body
|
|
|
|
```json
|
|
{
|
|
"profile_picture_url": "https://your-media-url-or-minio-presigned-url"
|
|
}
|
|
```
|
|
|
|
#### Success response
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"status_code": 200,
|
|
"message": "Profile picture URL updated successfully",
|
|
"data": {
|
|
"profile_picture_url": "https://your-media-url-or-minio-presigned-url"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## B) Course Thumbnail
|
|
|
|
### `POST /api/v1/course-management/courses/:id/thumbnail`
|
|
|
|
**Old style:** multipart with `file`
|
|
**New style:** JSON with uploaded URL
|
|
|
|
#### JSON request body
|
|
|
|
```json
|
|
{
|
|
"thumbnail_url": "https://your-media-url-or-minio-presigned-url"
|
|
}
|
|
```
|
|
|
|
#### Success response
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Course thumbnail URL updated successfully",
|
|
"data": {
|
|
"thumbnail_url": "https://your-media-url-or-minio-presigned-url"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## C) Sub-course Thumbnail
|
|
|
|
### `POST /api/v1/course-management/sub-courses/:id/thumbnail`
|
|
|
|
**Old style:** multipart with `file`
|
|
**New style:** JSON with uploaded URL
|
|
|
|
#### JSON request body
|
|
|
|
```json
|
|
{
|
|
"thumbnail_url": "https://your-media-url-or-minio-presigned-url"
|
|
}
|
|
```
|
|
|
|
#### Success response
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Sub-course thumbnail URL updated successfully",
|
|
"data": {
|
|
"thumbnail_url": "https://your-media-url-or-minio-presigned-url"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## D) Audio Answer Submission
|
|
|
|
### `POST /api/v1/questions/audio-answer`
|
|
|
|
**Old style:** multipart with `question_id`, `question_set_id`, `file`
|
|
**New style:** JSON referencing uploaded audio object key
|
|
|
|
#### JSON request body
|
|
|
|
```json
|
|
{
|
|
"question_id": 101,
|
|
"question_set_id": 5,
|
|
"object_key": "audio/uuid-audio-file.webm"
|
|
}
|
|
```
|
|
|
|
#### Success response
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"status_code": 200,
|
|
"message": "Audio answer submitted successfully",
|
|
"data": {
|
|
"id": 1,
|
|
"question_id": 101,
|
|
"question_set_id": 5,
|
|
"audio_url": "https://...",
|
|
"created_at": "2026-03-24T10:30:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 3) Recommended Admin Panel Integration Flow
|
|
|
|
For each image/audio/video field:
|
|
|
|
1. Call `POST /api/v1/files/upload` with `multipart/form-data`
|
|
2. Read response `data`
|
|
- image/audio: use `url` (and keep `object_key` if needed)
|
|
- video: use `url` / `vimeo_id` / `embed_url` depending on target endpoint
|
|
3. Call business endpoint with JSON body using returned media reference
|
|
|
|
---
|
|
|
|
## 4) Endpoint List (Quick Reference)
|
|
|
|
- `POST /api/v1/files/upload` (new)
|
|
- `POST /api/v1/user/:id/profile-picture` (now supports JSON)
|
|
- `POST /api/v1/course-management/courses/:id/thumbnail` (now supports JSON)
|
|
- `POST /api/v1/course-management/sub-courses/:id/thumbnail` (now supports JSON)
|
|
- `POST /api/v1/questions/audio-answer` (now supports JSON)
|
|
|
|
---
|
|
|
|
## 5) Backward Compatibility Note
|
|
|
|
Legacy multipart behavior for the updated endpoints is still supported to avoid breaking existing clients during migration.
|
|
Admin panel should migrate to the new JSON-reference flow for consistency.
|
|
|