Upload

Chunked file upload and download for drive files via presigned storage URLs.

File upload and download for drive files. File records are created via the Files service. Binary content is then uploaded directly to cloud storage through presigned URLs.

Unlike tasks/notes where attachments are children of the main entity, in drive the File record IS the entity — it owns chunks directly. Access is checked against file_user_role on the file itself.

Service: drive.upload

Upload flow

  1. Create a file record via drive.files.create with kind: "file" and size_bytes. The server returns the assigned id with status: "pending"
  2. Call requestUploadUrl to get a presigned upload URL for each chunk
  3. PUT the encrypted chunk body to the presigned URL (standard HTTP PUT, not WebSocket)
  4. Call confirmChunk for each uploaded chunk — the server verifies the upload and registers the chunk
  5. Repeat steps 2–4 for all chunks
  6. Call finalizeUpload to mark the file as ready

For thumbnails repeat steps 2–4 with chunk_type: "thumbnail_128" (single chunk). Thumbnails do not require a separate finalize call — the server sets thumbnail_128_id automatically on confirm.

requestUploadUrl

Request a presigned upload URL for a single chunk.

WebSocket

Request

{
  "jsonrpc": "2.0",
  "method": "drive.upload.requestUploadUrl",
  "params": {
    "file_id": "1920438291510",
    "object_key": "a1/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  },
  "id": 30
}
Param Type Required Description
file_id string File record id
object_key string Client-generated object key for storage (format: <uuid[:2]>/<uuid>)
chunk_type string "file" (default) or "thumbnail_128"

Response

{
  "jsonrpc": "2.0",
  "result": {
    "object_key": "a1/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "upload_url": "https://storage.example.com/enbox-drive-files/a1/a1b2c3d4-e5f6-7890-abcd-ef1234567890?X-Amz-..."
  },
  "id": 30
}

confirmChunk

Confirm that a chunk was successfully uploaded. The server HEAD-verifies the object in S3, creates a Chunk row, and links it to the file via FileChunk.

WebSocket

Request

{
  "jsonrpc": "2.0",
  "method": "drive.upload.confirmChunk",
  "params": {
    "file_id": "1920438291510",
    "object_key": "a1/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "chunk_index": 0
  },
  "id": 31
}
Param Type Required Description
file_id string File record id
object_key string Object key used during upload
chunk_index integer 0-based chunk order. Default 0
chunk_type string "file" (default) or "thumbnail_128"

Response

{
  "jsonrpc": "2.0",
  "result": {
    "chunk_id": "1920438291580",
    "chunk_index": 0,
    "size_bytes": 262188
  },
  "id": 31
}

finalizeUpload

Mark the file as ready after all content chunks have been uploaded and confirmed. The server verifies that at least one file chunk exists.

WebSocket

Request

{
  "jsonrpc": "2.0",
  "method": "drive.upload.finalizeUpload",
  "params": {
    "file_id": "1920438291510"
  },
  "id": 32
}
Param Type Required Description
file_id string File record id

Response

{
  "jsonrpc": "2.0",
  "result": {
    "file_id": "1920438291510",
    "status": "ready"
  },
  "id": 32
}

requestDownloadUrls

Request presigned download URLs for specific chunks of a file.

WebSocket

Request

{
  "jsonrpc": "2.0",
  "method": "drive.upload.requestDownloadUrls",
  "params": {
    "file_id": "1920438291510",
    "chunk_indexes": [0, 1]
  },
  "id": 33
}
Param Type Required Description
file_id string File record id
chunk_indexes integer[] 0-based indexes of chunks to download
chunk_type string "file" (default) or "thumbnail_128"

Response

{
  "jsonrpc": "2.0",
  "result": [
    {
      "chunk_index": 0,
      "download_url": "https://storage.example.com/enbox-drive-files/a1/a1b2c3d4-...?X-Amz-...",
      "size_bytes": 262188
    },
    {
      "chunk_index": 1,
      "download_url": "https://storage.example.com/enbox-drive-files/b2/b2c3d4e5-...?X-Amz-...",
      "size_bytes": 131116
    }
  ],
  "id": 33
}

For thumbnails (chunk_type: "thumbnail_128") use chunk_indexes: [0]. The result contains a single entry or an empty array if no thumbnail exists.

Danger: chunk_indexes is required. The server does not support returning all chunks in one call — the client must specify exactly which chunks it needs. This keeps presign cost explicit and enables partial/range-request streaming.