Skip to Content
API 參考附件

附件

執行可續傳的分段上傳,並透過資料列、欄位與租戶權限檢查安全下載附件。

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_idpathuuid之後會擁有此附件檔案物件的自訂資料表 UUID。

回應結構

InitMultipartUploadResponse
欄位型別必填說明
chunk_sizeintegerSize of each chunk in bytes
expires_atstringISO format timestamp when the session expires
session_idstringUnique identifier for this upload session
total_chunksintegerTotal 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 內。
{
  "detail": "File size must be greater than 0"
}
400檔案或分塊大小不合法、檔案超過資料表 attachment 欄位中最大的上限,或 MIME type 不在任何 attachment 欄宣告的 allowlist 內。
{
  "detail": "Content type 'application/zip' is not accepted by any attachment column on this table"
}
403呼叫者沒有新增或編輯能力,或不屬於任何公司。
{
  "detail": "Write access (insert or edit) not granted for this table."
}
404table_id 無法解析成現行自訂資料表。
{
  "detail": "Custom table not found"
}
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
欄位型別必填說明
chunkstringThe chunk data
chunk_hashstring | nullSHA-256 hash of the chunk for integrity verification
chunk_indexintegerZero-based index of this chunk
session_idstringUpload session ID

回應結構

UploadChunkResponse
欄位型別必填說明
chunk_indexintegerIndex of the uploaded chunk
is_completebooleanWhether all chunks have been uploaded
progress_percentnumberUpload progress as a percentage
session_idstringUpload session ID
total_chunksintegerTotal number of chunks expected
uploaded_chunksinteger[]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
}

錯誤

狀態發生條件錯誤本文
400Index 超出工作階段範圍、非最後一塊大小不等於 chunk_size、最後一塊大小不等於剩餘 bytes,或 chunk_hash 與 SHA-256 digest 不符。
{
  "detail": "Invalid chunk index. Expected 0-0, got 1"
}
403Storage service 拒絕存取。這是基礎設施授權,不是 custom-table 使用者權限回應。
{
  "detail": "Access denied to S3 bucket. Please check S3 permissions."
}
404Session id 不存在或 24 小時工作階段已過期;過期工作階段會被清理。
{
  "detail": "Upload session not found or expired"
}
409該 zero-based chunk index 已被接受,或另一個並行上傳先取得同一 part。
{
  "detail": "Chunk 0 has already been uploaded"
}
413Storage provider 判定此 part 過大。
{
  "detail": "Chunk size exceeds S3 limits"
}
503Redis 或 object storage 不可用,或損壞的 provider upload 無法復原。
{
  "detail": "Storage service temporarily unavailable"
}
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_idpathuuid初始化此上傳工作階段時使用的資料表 UUID。

回應結構

AttachmentUploadResponse
欄位型別必填說明
blobAttachmentInfoUploaded 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 不同)。
{
  "detail": "Not all chunks uploaded. Missing chunks: [0]"
}
403工作階段屬於其他使用者,或呼叫者已失去寫入權限。
{
  "detail": "You don't have permission to use this upload session"
}
404工作階段已過期,或資料表已不存在。
{
  "detail": "Upload session not found or expired"
}
409寫入 blob 資料列時遇到暫時性鎖衝突。分塊已經組裝完成,物件與 session(24 小時 TTL)都還在——拿同一個 session_id 重呼 complete 收尾;這個重試具冪等性。
{
  "detail": "Concurrent write conflict (lock); please retry the request."
}
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_idpathuuid初始化此上傳工作階段時使用的資料表 UUID。
session_idqueryuuid要取消的上傳工作階段 UUID。

回應結構

SuccessResponse
欄位型別必填說明
messagestring未指定

範例

中止未完成的上傳

請求
{
  "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工作階段屬於其他使用者,或呼叫者沒有資料表寫入權限。
{
  "detail": "You don't have permission to use this upload session"
}
404工作階段已過期、已完成,或先前已中止。
{
  "detail": "Upload session not found or already completed"
}
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_idpathuuid初始化此上傳工作階段時使用的資料表 UUID。
session_idqueryuuid要查詢進度的上傳工作階段 UUID。

回應結構

SessionStatusResponse
欄位型別必填說明
chunk_sizeintegerSize of each chunk in bytes
content_typestringMIME type of the file
created_atstringISO format timestamp when session was created
expires_atstringISO format timestamp when session expires
file_sizeintegerTotal file size in bytes
filenamestringName of the file being uploaded
is_completebooleanWhether all chunks have been uploaded
missing_chunksinteger[]List of chunk indices that haven't been uploaded yet
progress_percentnumberUpload progress as a percentage
session_idstringUpload session identifier
total_chunksintegerTotal number of chunks
uploaded_chunksinteger[]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工作階段屬於其他使用者,或呼叫者沒有資料表寫入權限。
{
  "detail": "You don't have permission to use this upload session"
}
404工作階段不存在或已過期。
{
  "detail": "Upload session not found or expired"
}
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_idpathuuid包含附件欄位的資料表 UUID。
record_idpathuuid實際參照此檔案物件,且呼叫者可讀取的資料列 UUID。
blob_idpathuuid保存在可見附件儲存格中的檔案物件 UUID。

回應結構

BlobInfoWithSignedUrl
欄位型別必填說明
content_typestringMIME type of the blob content
created_atstringTimestamp when the blob was uploaded
expiration_secondsintegerAlways 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_atstringResponse-construction timestamp for this endpoint when expiration_seconds is 0. It is not a URL expiry or a refresh deadline.
filenamestring | nullOriginal filename of the uploaded content, if available
idstringUnique identifier for the blob
signed_urlstringLegacy 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.
tagsstring[]Tags associated with the blob (parsed from comma-separated string)
thumbnail_BlobInfo | nullInformation about an associated thumbnail blob, if available
urlstring | nullAlways 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呼叫者沒有此資料表的讀取權限。
{
  "detail": "Read access not granted for this table."
}
404資料表或資料列無法讀取、可見附件欄位未參照此 blob,或 blob 屬於其他租戶。
{
  "detail": "Attachment not found"
}
Last updated on