Docs

Working with files

Paths and folders, uploading (and replacing), large files with resumable uploads, listing, moving and renaming, downloading and deleting, and the limits that apply.

Updated Oct 17, 2026Open in console

Paths and folders

A file is addressed by its bucket and a path: avatars + 6e19…/photo.png. Folders are just the parts of the path before the last /; they exist as long as something is in them (New folder in the console creates an empty placeholder). Use the user's id as the first folder for per-user files — the own folder rules check exactly that (Access, links and delivery).

Keep names URL-safe (letters, digits, -, _, ., /); the SDKs encode anything else.

Upload

const user = await sovaria.auth.me()
await sovaria.storage.upload('avatars', `${user.id}/photo.png`, file, {
  contentType: 'image/png',
  upsert: true,          // replace the file if it exists
})
SituationResult
The path is newThe file is stored.
The path exists, without upsert409 Object … already exists — nothing is overwritten.
The path exists, with upsert: trueThe file is replaced. There is no version history for files.
Bigger than the bucket's or plan's largest file413.
Type not in the bucket's allowed typesRefused.
The project's storage is full403 with a plan code (Free stops; paid plans bill beyond — Billing, invoices and overage).

For browser uploads straight to Sovaria without passing through your server, create a signed upload URL on your server and let the browser PUT the file to it (Access, links and delivery).

Large files: resumable uploads

For files of tens of megabytes or more, or unreliable networks, upload in chunks and resume after a failure (a TUS-style protocol):

  1. Start

    Returns 201 with a Location header for the upload.

    curl -si -X POST "$URL/api/v1/store/resumable/videos/$USER_ID/clip.mp4" \
      -H "Authorization: Bearer $TOKEN" -H "Upload-Length: 734003200"
    # Location: /api/v1/store/resumable/<upload-id>   Upload-Offset: 0
  2. Send chunks

    Each PATCH carries the offset it starts at; a wrong offset is refused so chunks can't be appended twice.

    curl -s -X PATCH "$URL/api/v1/store/resumable/<upload-id>" \
      -H "Authorization: Bearer $TOKEN" -H "Upload-Offset: 0" \
      -H 'Content-Type: application/offset+octet-stream' --data-binary @chunk-0
  3. Resume after a failure

    HEAD the upload to read Upload-Offset, then continue from there.

  4. Finish

    Send the last chunk with X-Upload-Complete: 1; the file appears in the bucket.

The S3-compatible storage access API also supports multipart uploads, so aws s3 cp, rclone and S3 libraries handle large files for you.

List, move, rename, delete

const files = await sovaria.storage.listObjects('avatars', { prefix: `${user.id}/` })

// Move or rename (both paths are bucket/path)
await sovaria.storage.moveObject({ from_path: `avatars/${user.id}/old.png`, to_path: `avatars/${user.id}/new.png` })

await sovaria.storage.remove('avatars', `${user.id}/new.png`)
  • Listing returns each file's path, size, content type and last change.
  • A move needs WRITE permission on both the old and the new path.
  • Deleting is immediate and permanent — there is no trash. Deleting a bucket deletes every file in it.

Download

sovaria.storage.download(bucket, path) returns a Blob for the signed-in user. For <img> tags and links, use a public URL (public buckets) or a signed URL (private ones) instead of downloading in JavaScript — Access, links and delivery.

Limits

FreeProUltraTeamEnterprise
Object storage1 GB100 GB300 GB1 TB5 TB
Files100 MB2 GB10 GB50 GB100 GB
Buckets31005002,00010,000
Monthly bandwidth5,368,709,120107,374,182,400322,122,547,2001,099,511,627,7765,497,558,138,880

A bucket can set a lower largest-file size and a list of allowed content types (Bucket › Settings, or file_size_limit / allowed_mime_types when creating it).

Something unclear or missing on this page?Tell us