Files
The following paths are relative to /api/v1 and require authentication.
Endpoints
Section titled “Endpoints”| Method | Path | Description |
|---|---|---|
POST | /files/upload | Ordinary multipart direct upload |
POST | /files/new | Create an empty file |
POST | /files/upload/init | Negotiate upload mode |
GET | /files/upload/sessions | List recoverable upload sessions |
PUT | /files/upload/{upload_id}/{chunk_number} | Upload one chunk |
POST | /files/upload/{upload_id}/presign-parts | Request object-storage / remote multipart part URLs |
POST | /files/upload/{upload_id}/complete | Assemble chunks or confirm presigned upload |
GET | /files/upload/{upload_id} | Read upload progress |
DELETE | /files/upload/{upload_id} | Cancel upload |
GET | /files/{id} | Read file metadata |
GET | /files/{id}/archive-preview | Read read-only archive preview manifest |
GET | /files/{id}/direct-link | Create direct-download token |
POST | /files/{id}/preview-link | Create short-lived preview link |
POST | /files/{id}/resource-handle | Resolve a frontend-consumable file resource contract |
POST | /files/{id}/wopi/open | Create WOPI launch session |
GET | /files/{id}/download | Download file content |
GET | /files/{id}/thumbnail | Get thumbnail |
GET | /files/{id}/image-preview | Get WebP image preview |
GET | /files/{id}/media-metadata | Get image / audio / video metadata |
PUT | /files/{id}/content | Overwrite content and write version history |
POST | /files/{id}/extract | Create archive extraction task |
PATCH | /files/{id} | Rename or move file |
DELETE | /files/{id} | Soft-delete to trash |
POST | /files/{id}/lock | Lock / unlock file |
POST | /files/{id}/copy | Copy file |
GET | /files/{id}/versions | List versions |
POST | /files/{id}/versions/{version_id}/restore | Restore a version |
DELETE | /files/{id}/versions/{version_id} | Delete a version |
Uploads
Section titled “Uploads”Primary upload entries:
POST /files/upload/init: negotiate mode firstPOST /files/upload: ordinary multipart uploadGET /files/upload/sessions: recover unfinished sessions after refresh
Directory-upload semantics are supported through:
folder_idrelative_pathdeclared_sizefrontend_client_id
folder_id = null means root. Missing directories in relative_path are created automatically. Empty path segments such as docs//bad.txt are rejected.
Negotiation returns one of four modes:
direct: small-file direct uploadchunked: resumable chunked uploadpresigned: single object-storage or remote presignedPUTpresigned_multipart: object-storage or remote multipart direct upload; the client must request part URLs separately
The frontend never sees an additional relay_stream mode. Actual transfer strategy is decided by storage connectors and policy options:
options.object_storage_upload_strategy: transfer strategy for S3-compatible, Azure Blob, and Tencent COS object-storage connectorsoptions.remote_upload_strategy- OneDrive uses Microsoft Graph native upload capabilities and follows the upload workflow exposed by the connector
relay_stream:initstill returnsdirect/chunked, but the server relays bytes straight to object storage / follower instead of writing a local temp filepresigned:initreturnspresigned/presigned_multipart
Object-storage and remote uploads fall back to relay_stream by default. Legacy {"presigned_upload":true} and {"s3_upload_strategy":"presigned"} are accepted as compatibility inputs for object-storage presigned upload; new clients should send {"object_storage_upload_strategy":"presigned"}.
Presigned browser uploads require usable CORS on the object storage or follower internal storage endpoint. Azure Blob presigned upload uses SAS URLs and requires x-ms-blob-type: BlockBlob; S3-compatible, Tencent COS, and Remote multipart parts usually require returned ETags. Remote presigned upload only works for directly reachable remote nodes; reverse-tunnel remote nodes reject remote_upload_strategy = "presigned".
Direct, chunked, and completion stages
Section titled “Direct, chunked, and completion stages”POST /files/upload: ordinary multipart upload; empty files are rejected, and same-folder same-name files are not overwritten. With object-storage / Remoterelay_stream, the body is relayed directly to the target driver.POST /files/new: creates a 0-byte file for “new text file” style actionsGET /files/upload/sessions: lists unexpired, recoverable sessions inuploading/assembling/presignedstatus;frontend_client_idcan filter sessions created by the same frontend instancePUT /files/upload/{upload_id}/{chunk_number}: uploads one chunk, withchunk_numberstarting at0POST /files/upload/{upload_id}/presign-parts: used only forpresigned_multipartGET /files/upload/{upload_id}: returns upload progress used by resumable uploadPOST /files/upload/{upload_id}/complete: completeschunked,presigned, orpresigned_multipart
Recoverable session fields include:
upload_idmodestatusfilenametotal_sizechunk_sizetotal_chunksreceived_countfolder_idchunks_on_diskcompleted_partsexpires_atupdated_at
Completion behavior:
- local path: validates size and quota; if local
content_dedupis enabled, computes SHA-256 and deduplicates blobs - object-storage / OneDrive / Remote paths: validate size and quota but do not deduplicate; each upload creates an independent blob using an upload-session-derived opaque hash and
files/{upload_id}-style object path
POST /files/new follows the same rule: local content dedup can reuse the 0-byte blob, while non-local connectors always create an independent blob.
presigned_multipart completion must include object-storage returned parts; other modes may omit the body.
File operations
Section titled “File operations”GET /files/{id}: read metadata; trashed files behave as not foundGET /files/{id}/archive-preview: read archive manifest; returns202and queuesarchive_preview_generateif not readyGET /files/{id}/direct-link: returns a short token; real download is/d/{token}/{filename}POST /files/{id}/preview-link: returns a short preview link; real content is/pv/{token}/{filename}POST /files/{id}/resource-handle: resolves the resource URL, credentials, cache identity, and redirect policy for the requested purpose and representationPOST /files/{id}/wopi/open: creates a WOPI launch session for a configured WOPI previewerGET /files/{id}/download: streams file content or redirects to a presigned GET URL when policy says so; supportsIf-None-MatchGET /files/{id}/thumbnail: returns thumbnail, or202withRetry-Afterwhile generatingGET /files/{id}/image-preview: returns raw WebP withETag, or202withRetry-Afterwhile generatingGET /files/{id}/media-metadata: returns blob-cached metadata, or202while queuedPUT /files/{id}/content: overwrite existing content, check locks, create version history, and return a newETagPOST /files/{id}/extract: creates an archive extraction taskPATCH /files/{id}: rename or moveDELETE /files/{id}: soft-delete to trash
File info and list items include persisted classification fields:
extension: lowercase final extension without dotcompound_extension: lowercase compound extension such astar.gzfile_category:image,video,audio,document,spreadsheet,presentation,archive,code, orother
These fields are recalculated on create, upload, overwrite, and rename.
Detail responses from GET /files/{id} and GET /teams/{team_id}/files/{id} also include storage_used. This is the quota-accounting size for the file detail view: current size plus all historical version sizes. Directory list items omit this field.
POST /files/{id}/resource-handle
Section titled “POST /files/{id}/resource-handle”File details answer what a file is. A resource handle answers how the current client should consume it. Request example:
{ "purpose": "preview", "delivery_mode": "blob_url", "representation": "auto"}Allowed values:
purpose:preview,download,external_viewerdelivery_mode:blob_url,text,direct_url,media_stream,iframe_session,manifestrepresentation:auto,original,image_preview,thumbnail; omitted values default toauto
Core response contract:
{ "code": "success", "msg": "", "data": { "identity": { "cache_key": "/api/v1/files/42/download", "etag": "\"blob-hash\"", "scope": "personal" }, "request": { "url": "/api/v1/files/42/download?disposition=inline", "credentials": "include", "conditional_headers": "allowed", "redirect_policy": "same_origin_only" }, "delivery": { "mode": "blob_url", "mime_type": "image/jpeg" } }}identity.cache_key is the stable resource identity, while request.url is the concrete URL for this request. etag, conditional_headers, and credentials tell the frontend whether conditional requests and login credentials are appropriate. redirect_policy = "may_cross_origin" means the URL can be a short-lived OneDrive or object-storage direct URL.
For auto + preview + blob_url, browser-hostile image formats such as HEIC, RAW, and TIFF may resolve to a derived WebP image-preview path. Sandbox-sensitive MIME types such as HTML remain on the same-origin path rather than bypassing isolation through a provider direct URL.
PATCH /files/{id}
Section titled “PATCH /files/{id}”Request:
{ "name": "renamed.pdf", "folder_id": 5}Supports rename, move, and folder_id = null to move to root. Name conflicts at the destination are rejected, and locked files cannot be modified.
Thumbnails
Section titled “Thumbnails”Thumbnail support comes from the media processing registry and is exposed anonymously through /public/thumbnail-support. The built-in images processor covers common image formats. The built-in lofty processor can expose audio suffixes for embedded cover thumbnails. Optional vips_cli / ffmpeg_cli processors contribute additional extensions only when enabled and available.
Storage policies can also contribute storage-native thumbnail and image-preview support with storage_native_processing_enabled = true, thumbnail_processor = "storage_native", and thumbnail_extensions. Built-in tencent_cos policies can expose this through COS CI; built-in Local, S3-compatible, Azure Blob, OneDrive, and Remote policies do not expose native thumbnail or image-preview capabilities.
Thumbnails return WebP and reuse cache by blob, processor, processor version, and effective max dimension. The max source byte limit is controlled by thumbnail_max_source_bytes; the rendered longest edge is controlled by runtime config thumbnail_max_dimension.
The default thumbnail dimension keeps the legacy cache version namespace. Non-default dimensions add a -d{dimension} suffix to the derivative version, so changing the configured size does not overwrite or accidentally reuse a different-size cache entry.
Image previews
Section titled “Image previews”Image preview endpoints return larger WebP images for preview panels and are separate from thumbnails:
- thumbnails are list/card-oriented and may return
202 - image previews are previewer-oriented; cache hits return raw WebP, while cache misses enqueue
image_preview_generateand return202withRetry-After - image previews use runtime config
image_preview_max_dimensionfor the rendered longest edge - unsupported types return file/thumbnail-domain errors instead of falling back to original bytes
- the frontend can choose its default strategy from
/public/frontend-configfieldmedia.image_preview_preference
The supported image-preview extensions are the same public capability union advertised by /public/thumbnail-support under image thumbnail/preview support. They can come from backend media processors or a storage-native provider such as Tencent COS when the policy opts in. Image-preview caches follow the same dimension-aware derivative-version rule as thumbnails.
Media metadata
Section titled “Media metadata”Media metadata is cached by blob. Image metadata is read by the built-in images processor, audio by lofty, and video by ffprobe_cli. media_metadata_enabled is the master switch, while per-kind settings live in media_processing_registry_json.
Storage-native media metadata can be enabled per policy with storage_native_processing_enabled = true, storage_native_media_metadata_enabled = true, and media_metadata_extensions. Built-in tencent_cos policies can expose native audio/video metadata through COS CI; built-in Local, S3-compatible, Azure Blob, OneDrive, and Remote policies do not expose native media metadata.
Audio embedded cover art is exposed through the existing thumbnail path when the lofty processor has thumbnail:audio.
Archive preview
Section titled “Archive preview”GET /files/{id}/archive-preview returns a read-only manifest for supported archive files without extracting them into the workspace.
Optional filename_encoding controls ZIP entry-name decoding:
autoutf8gb18030cp437cp850shift_jisbig5euc_krwindows_1252
Explicit values override auto detection.
Response shape:
{ "code": "success", "msg": "", "data": { "schema_version": 2, "format": "zip", "source_blob_id": 42, "source_hash": "abc...", "generated_at": "2026-05-18T12:00:00Z", "entry_count": 2, "file_count": 1, "directory_count": 1, "total_uncompressed_size": 128, "truncated": false, "entries": [ { "path": "docs/readme.txt", "name": "readme.txt", "parent": "docs", "kind": "file", "size": 128, "compressed_size": 64, "modified_at": "2026-05-18T12:00:00Z" } ] }}Current implementation:
- supports
.zipand corresponding MIME types - disabled by default; requires both
archive_preview_enabledandarchive_preview_user_enabled - first uncached request queues or reuses
archive_preview_generateand returns202 - raw manifest is cached under
entity_propertiesassystem.archive_preview / zip_raw_manifest.v2 - success responses include
ETagand supportIf-None-Match - limits are controlled by archive-preview and archive-extraction runtime settings
- range-capable storage drivers are used for metadata scanning when possible
Direct and preview links
Section titled “Direct and preview links”GET /files/{id}/direct-link returns only a token. The actual URL is:
/d/{token}/{filename}POST /files/{id}/preview-link returns PreviewLinkInfo; actual content is served from:
/pv/{token}/{filename}These root-level endpoints return raw file data or redirects instead of wrapped JSON.