附件
執行可續傳的分段上傳,並透過資料列、欄位與租戶權限檢查安全下載附件。
POST
路由範本
/private/module/custom_tables/{scopeName}/tables/{table_id}/blobs/multipart/init用途
替準備寫入自訂資料表附件儲存格的檔案建立可續傳工作階段。
適用時機
傳送新附件的第一個分塊前,先呼叫此端點。
實際掛載路徑
- 聊天室
/private/module/custom_tables/chatroom/tables/{table_id}/blobs/multipart/init - 部門
/private/module/custom_tables/department/tables/{table_id}/blobs/multipart/init - 公司
/private/module/custom_tables/company/tables/{table_id}/blobs/multipart/init
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 可使用 | CustomTableWriteRequired |
| 部門 | 可使用 | CustomTableWriteRequired |
| 公司 | 可使用 | CustomTableWriteRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | 之後會擁有此附件檔案物件的自訂資料表 UUID。 |
回應結構
InitMultipartUploadResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
chunk_size | integer | 是 | Size of each chunk in bytes |
expires_at | string | 是 | ISO format timestamp when the session expires |
session_id | string | 是 | Unique identifier for this upload session |
total_chunks | integer | 是 | Total number of chunks expected |
範例
開始上傳只有一個分塊的文字檔
請求
{
"pathParams": {
"table_id": "22222222-2222-4222-8222-222222222222"
},
"body": {
"filename": "order-note.txt",
"file_size": 18,
"content_type": "text/plain"
}
}回應201
{
"session_id": "55555555-5555-4555-8555-555555555555",
"chunk_size": 5242880,
"total_chunks": 1,
"expires_at": "2026-07-20T02:30:00"
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 400 | 檔案或分塊大小不合法、檔案超過資料表 attachment 欄位中最大的上限,或 MIME type 不在任何 attachment 欄宣告的 allowlist 內。 | |
| 400 | 檔案或分塊大小不合法、檔案超過資料表 attachment 欄位中最大的上限,或 MIME type 不在任何 attachment 欄宣告的 allowlist 內。 | |
| 403 | 呼叫者沒有新增或編輯能力,或不屬於任何公司。 | |
| 404 | table_id 無法解析成現行自訂資料表。 | |
POST
路由範本
/public/module/etl/multipart/chunk用途
把一個從 0 起算的 binary part,上傳到 multipart init 回傳的可續傳工作階段。
適用時機
Init 之後、complete 之前,每個 chunk 各呼叫一次;缺少或需要重試的 chunk 可依任意順序送出。
實際掛載路徑
- 完整路由
/public/module/etl/multipart/chunk
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 完整路由 | 可使用 | UploadSessionCapability |
請求結構
Body_upload_chunk_public_module_etl_multipart_chunk_post| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
chunk | string | 是 | The chunk data |
chunk_hash | string | null | 否 | SHA-256 hash of the chunk for integrity verification |
chunk_index | integer | 是 | Zero-based index of this chunk |
session_id | string | 是 | Upload session ID |
回應結構
UploadChunkResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
chunk_index | integer | 是 | Index of the uploaded chunk |
is_complete | boolean | 是 | Whether all chunks have been uploaded |
progress_percent | number | 是 | Upload progress as a percentage |
session_id | string | 是 | Upload session ID |
total_chunks | integer | 是 | Total number of chunks expected |
uploaded_chunks | integer[] | 是 | List of all successfully uploaded chunk indices |
範例
上傳小檔案唯一的一個分塊
請求
{
"pathParams": {},
"body": {
"session_id": "55555555-5555-4555-8555-555555555555",
"chunk_index": 0,
"chunk": "<binary chunk: 18 bytes>",
"chunk_hash": "96c4b7d5fb8e6ef963fab7b8708fd574a3836fabb46539d22af6ca68ac3b27ff"
}
}回應200
{
"session_id": "55555555-5555-4555-8555-555555555555",
"chunk_index": 0,
"uploaded_chunks": [
0
],
"total_chunks": 1,
"progress_percent": 100,
"is_complete": true
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 400 | Index 超出工作階段範圍、非最後一塊大小不等於 chunk_size、最後一塊大小不等於剩餘 bytes,或 chunk_hash 與 SHA-256 digest 不符。 | |
| 403 | Storage service 拒絕存取。這是基礎設施授權,不是 custom-table 使用者權限回應。 | |
| 404 | Session id 不存在或 24 小時工作階段已過期;過期工作階段會被清理。 | |
| 409 | 該 zero-based chunk index 已被接受,或另一個並行上傳先取得同一 part。 | |
| 413 | Storage provider 判定此 part 過大。 | |
| 503 | Redis 或 object storage 不可用,或損壞的 provider upload 無法復原。 | |
POST
路由範本
/private/module/custom_tables/{scopeName}/tables/{table_id}/blobs/multipart/complete用途
組合所有已上傳分塊、建立歸屬正確租戶的檔案物件,並回傳已遮蔽網址的附件資訊。
適用時機
狀態顯示所有預期分塊都已上傳後再呼叫。
實際掛載路徑
- 聊天室
/private/module/custom_tables/chatroom/tables/{table_id}/blobs/multipart/complete - 部門
/private/module/custom_tables/department/tables/{table_id}/blobs/multipart/complete - 公司
/private/module/custom_tables/company/tables/{table_id}/blobs/multipart/complete
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 可使用 | CustomTableWriteRequired |
| 部門 | 可使用 | CustomTableWriteRequired |
| 公司 | 可使用 | CustomTableWriteRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | 初始化此上傳工作階段時使用的資料表 UUID。 |
回應結構
AttachmentUploadResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
blob | AttachmentInfo | 是 | Uploaded attachment metadata (url-redacted) |
範例
組合已完成上傳的文字檔
請求
{
"pathParams": {
"table_id": "22222222-2222-4222-8222-222222222222"
},
"body": {
"session_id": "55555555-5555-4555-8555-555555555555"
}
}回應200
{
"blob": {
"id": "44444444-4444-4444-8444-444444444444",
"created_at": "2026-07-19 02:35:00",
"url": null,
"content_type": "text/plain",
"filename": "order-note.txt",
"size_bytes": 18
}
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 400 | 仍有分塊缺漏、table_id 與工作階段不符,或重新量測後的組裝物件超過整張表最大的附件上限。超限拒絕是終局的——物件會被刪除、工作階段會被清除,必須從 init 重新開始(與可重試的 409 不同)。 | |
| 403 | 工作階段屬於其他使用者,或呼叫者已失去寫入權限。 | |
| 404 | 工作階段已過期,或資料表已不存在。 | |
| 409 | 寫入 blob 資料列時遇到暫時性鎖衝突。分塊已經組裝完成,物件與 session(24 小時 TTL)都還在——拿同一個 session_id 重呼 complete 收尾;這個重試具冪等性。 | |
DELETE
路由範本
/private/module/custom_tables/{scopeName}/tables/{table_id}/blobs/multipart/abort用途
取消未完成的上傳,並移除暫存物件分塊與工作階段鍵值。
適用時機
使用者取消上傳,或工作階段已無法安全續傳時使用。
實際掛載路徑
- 聊天室
/private/module/custom_tables/chatroom/tables/{table_id}/blobs/multipart/abort - 部門
/private/module/custom_tables/department/tables/{table_id}/blobs/multipart/abort - 公司
/private/module/custom_tables/company/tables/{table_id}/blobs/multipart/abort
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 可使用 | CustomTableWriteRequired |
| 部門 | 可使用 | CustomTableWriteRequired |
| 公司 | 可使用 | CustomTableWriteRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | 初始化此上傳工作階段時使用的資料表 UUID。 |
session_id | query | uuid | 是 | 要取消的上傳工作階段 UUID。 |
回應結構
SuccessResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
message | string | 否 | 未指定 |
範例
中止未完成的上傳
請求
{
"pathParams": {
"table_id": "22222222-2222-4222-8222-222222222222"
},
"query": {
"session_id": "55555555-5555-4555-8555-555555555555"
}
}回應200
{
"message": "Upload session 55555555-5555-4555-8555-555555555555 has been aborted"
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 403 | 工作階段屬於其他使用者,或呼叫者沒有資料表寫入權限。 | |
| 404 | 工作階段已過期、已完成,或先前已中止。 | |
GET
路由範本
/private/module/custom_tables/{scopeName}/tables/{table_id}/blobs/multipart/status用途
回傳工作階段資訊、已上傳與缺少的分塊、進度、完成狀態及到期時間。
適用時機
適合用來續傳中斷的上傳,或判斷何時可以安全呼叫 complete。
實際掛載路徑
- 聊天室
/private/module/custom_tables/chatroom/tables/{table_id}/blobs/multipart/status - 部門
/private/module/custom_tables/department/tables/{table_id}/blobs/multipart/status - 公司
/private/module/custom_tables/company/tables/{table_id}/blobs/multipart/status
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 可使用 | CustomTableWriteRequired |
| 部門 | 可使用 | CustomTableWriteRequired |
| 公司 | 可使用 | CustomTableWriteRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | 初始化此上傳工作階段時使用的資料表 UUID。 |
session_id | query | uuid | 是 | 要查詢進度的上傳工作階段 UUID。 |
回應結構
SessionStatusResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
chunk_size | integer | 是 | Size of each chunk in bytes |
content_type | string | 是 | MIME type of the file |
created_at | string | 是 | ISO format timestamp when session was created |
expires_at | string | 是 | ISO format timestamp when session expires |
file_size | integer | 是 | Total file size in bytes |
filename | string | 是 | Name of the file being uploaded |
is_complete | boolean | 是 | Whether all chunks have been uploaded |
missing_chunks | integer[] | 是 | List of chunk indices that haven't been uploaded yet |
progress_percent | number | 是 | Upload progress as a percentage |
session_id | string | 是 | Upload session identifier |
total_chunks | integer | 是 | Total number of chunks |
uploaded_chunks | integer[] | 是 | List of successfully uploaded chunk indices |
範例
查看新建立的單分塊工作階段
請求
{
"pathParams": {
"table_id": "22222222-2222-4222-8222-222222222222"
},
"query": {
"session_id": "55555555-5555-4555-8555-555555555555"
}
}回應200
{
"session_id": "55555555-5555-4555-8555-555555555555",
"filename": "order-note.txt",
"file_size": 18,
"content_type": "text/plain",
"chunk_size": 5242880,
"total_chunks": 1,
"uploaded_chunks": [],
"missing_chunks": [
0
],
"progress_percent": 0,
"is_complete": false,
"created_at": "2026-07-19T02:30:00",
"expires_at": "2026-07-20T02:30:00"
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 403 | 工作階段屬於其他使用者,或呼叫者沒有資料表寫入權限。 | |
| 404 | 工作階段不存在或已過期。 | |
GET
路由範本
/private/module/custom_tables/{scopeName}/tables/{table_id}/records/{record_id}/attachments/{blob_id}/download用途
重新驗證資料列 ACL、附件欄位可見性與租戶歸屬後,回傳受控的檔案資訊與存取網址。
適用時機
使用者要開啟或下載附件儲存格中的 blob id 時使用。
實際掛載路徑
- 聊天室
/private/module/custom_tables/chatroom/tables/{table_id}/records/{record_id}/attachments/{blob_id}/download - 部門
/private/module/custom_tables/department/tables/{table_id}/records/{record_id}/attachments/{blob_id}/download - 公司
/private/module/custom_tables/company/tables/{table_id}/records/{record_id}/attachments/{blob_id}/download
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 可使用 | CustomTableReadRequired |
| 部門 | 可使用 | CustomTableReadRequired |
| 公司 | 可使用 | CustomTableReadRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | 包含附件欄位的資料表 UUID。 |
record_id | path | uuid | 是 | 實際參照此檔案物件,且呼叫者可讀取的資料列 UUID。 |
blob_id | path | uuid | 是 | 保存在可見附件儲存格中的檔案物件 UUID。 |
回應結構
BlobInfoWithSignedUrl| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
content_type | string | 是 | MIME type of the blob content |
created_at | string | 是 | Timestamp when the blob was uploaded |
expiration_seconds | integer | 是 | Always 0 for custom-table attachment downloads. Zero means this endpoint did not add a URL TTL; it is not an immediate expiry or a refresh interval. |
expires_at | string | 是 | Response-construction timestamp for this endpoint when expiration_seconds is 0. It is not a URL expiry or a refresh deadline. |
filename | string | null | 是 | Original filename of the uploaded content, if available |
id | string | 是 | Unique identifier for the blob |
signed_url | string | 是 | Legacy field containing the blob's stored URL after this endpoint passes its request-time authorization gates. The endpoint returns the stored URL unchanged; it does not cryptographically sign or time-limit it. |
tags | string[] | 否 | Tags associated with the blob (parsed from comma-separated string) |
thumbnail | _BlobInfo | null | 是 | Information about an associated thumbnail blob, if available |
url | string | null | 是 | Always null in the custom-table attachment download response; use the legacy signed_url field. |
範例
將可見附件解析成存取網址
請求
{
"pathParams": {
"table_id": "22222222-2222-4222-8222-222222222222",
"record_id": "33333333-3333-4333-8333-333333333333",
"blob_id": "44444444-4444-4444-8444-444444444444"
}
}回應200
{
"id": "44444444-4444-4444-8444-444444444444",
"created_at": "2026-07-19 02:35:00",
"url": null,
"content_type": "text/plain",
"filename": "order-note.txt",
"tags": [],
"thumbnail": null,
"signed_url": "https://files.example.invalid/custom-tables/order-note.txt",
"expires_at": "2026-07-19 02:40:00",
"expiration_seconds": 0
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 403 | 呼叫者沒有此資料表的讀取權限。 | |
| 404 | 資料表或資料列無法讀取、可見附件欄位未參照此 blob,或 blob 屬於其他租戶。 | |
Last updated on