5.8 KiB
5.8 KiB
File Manager
Uploading New File
Sebelum hit API, FE ambil data per file:
name(contoh:spidey.png)content_type(contoh:image/png)size_bytes(contoh:42170)
Step 1 - FE minta upload intent ke BE, lalu upload langsung ke storage
A. Minta Upload Intent ke Backend
Endpoint
POST /api/v1/file-manager/files/upload
FE kirim request ini
- Single File
{
"data": [
{
"type": "file_manager_file_upload_intent",
"attributes": {
"name": "image.png",
"content_type": "image/png",
"size_bytes": 123
}
}
]
}
- Bulk File
{
"data": [
{
"type": "file_manager_file_upload_intent",
"attributes": {
"name": "image1.png",
"content_type": "image/png",
"size_bytes": 123
}
},
{
"type": "file_manager_file_upload_intent",
"attributes": {
"name": "image2.png",
"content_type": "image/png",
"size_bytes": 456
}
}
]
}
Backend akan balas per file
upload_intent_uuidupload_urlmethod(PUT)required_headersobject.bucketobject.keyexpires_atexpires_in_seconds
Contoh response:
{
"data": [
{
"index": 0,
"success": true,
"resource": {
"type": "file_manager_file_upload_intent",
"id": "019d8215-c622-7576-86bd-3ddeecaf4867",
"attributes": {
"upload_intent_uuid": "019d8215-c622-7576-86bd-3ddeecaf4867",
"upload_url": "http://localhost:4566/...",
"method": "PUT",
"required_headers": {
"content-type": "image/png"
},
"object": {
"bucket": "wucher-file-dev",
"key": "fm/objects/files/2026/04/12/019d8215c6227a1aa20fc21f99f36584.png"
},
"file": {
"name": "spidey.png",
"mime_type": "image/png",
"size_bytes": 42170
},
"expires_at": "2026-04-12T14:40:58Z",
"expires_in_seconds": 899
}
}
}
],
"meta": {
"total": 1,
"success": 1,
"failed": 0,
"partial_success": false
}
}
B. FE Handle langsung Upload Binary Langsung ke S3
Untuk setiap item success: true dari step 1:
- Ambil
upload_url - Ambil
method - Ambil
required_headers(jika ada) - Lakukan request upload file ke S3
Contoh yang akan dilakukan FE:
await fetch(upload_url, {
method: method, // "PUT"
headers: { "Content-Type": file.type },
body: file,
});
atau pseudo
const intents = await api.requestUploadIntents(files) // bulk
const readyToUpload = intents.data.filter(i => i.success)
const uploadResults = await parallelLimit(readyToUpload, 4, putToS3) // paralel
const succeeded = uploadResults.filter(r => r.success)
if (succeeded.length > 0) {
await api.createFilesBulk(succeeded.map(toCreatePayload))
}
Catatan penting:
- 1 file = 1 PUT ke S3
- boleh paralel (disarankan pakai concurrency limit)
- file yang gagal PUT jangan dikirim ke step create
Step 2 - Upload Cancel (opsional)
Endpoint
DELETE /api/v1/file-manager/files/cancel-upload
FE kirim request ini
{
"data": [
{
"type": "file_manager_file_cancel_upload",
"attributes": {
"upload_intent_uuid": "019d8215-c622-7576-86bd-3ddeecaf4867"
}
}
]
}
Kapan dipakai
- user sudah request upload intent
- tapi user batal sebelum create
- FE bisa cancel upload intent supaya flow lebih bersih
Contoh response
{
"data": [
{
"index": 0,
"success": true,
"resource": {
"type": "file_manager_file_cancel_upload_result",
"id": "019d8215-c622-7576-86bd-3ddeecaf4867",
"attributes": {
"status": "canceled"
}
}
}
],
"meta": {
"total": 1,
"success": 1,
"failed": 0,
"partial_success": false
}
}
Step 3 - FE Panggil Create ke Backend (Finalisasi)
Setelah PUT S3 sukses, FE gunakan:
Endpoint
POST /api/v1/file-manager/files/create
FE kirim request ini
{
"data": [
{
"type": "file_manager_file_create",
"attributes": {
"upload_intent_uuid": "019d8215-c622-7576-86bd-3ddeecaf4867",
"name": "spidey.png",
"folder_id": null
}
}
]
}
Aturan:
upload_intent_uuid: wajibname: wajibfolder_id: opsional (kalau mau dimasukkan ke folder)nullatau tidak dikirim = root
Step 4 - Process Create (BE)
Untuk setiap item:
- Ambil upload intent dari
upload_intent_uuid - Verify object benar-benar ada di storage
- Verify metadata object (size/content type) sesuai intent
- Simpan metadata file ke DB
- Simpan outbox durable
- Set status awal file menjadi
uploaded
Step 5 - Proses Async Lanjutan (Backend)
Setelah status uploaded, worker akan lanjut:
uploaded -> processing -> validated -> ready- atau
uploaded -> processing -> failed
Step 6 - FE Handle Response Create
Response create adalah bulk per item.
- Kalau semua sukses: HTTP
201 - Kalau campuran sukses + gagal: HTTP
207denganpartial_success: true
Contoh sukses:
{
"data": [
{
"index": 0,
"success": true,
"message": "created",
"resource": {
"type": "file_manager_file",
"id": "019d628a-8d92-7949-b355-95de506da3b7",
"attributes": {
"folder_id": "019d4309-4dc8-78be-bb0c-3ebb8f3056ba",
"name": "spidey01.png",
"extension": "png",
"size_bytes": 42170,
"mime_type": "image/png",
"status": "uploaded",
"created_at": "2026-04-06T11:25:40Z",
"updated_at": "2026-04-06T11:25:40Z"
}
}
}
],
"meta": {
"total": 1,
"success": 1,
"failed": 0,
"partial_success": false
}
}