On this page

Upload and download

Upload files from the browser, serve them back and manage them.

#Upload

JavaScript
const file = event.target.files[0]
const { data, error } = await stitchdb.storage
  .from('avatars')
  .upload(`${user.id}/avatar.png`, file, { upsert: true })

const { data: { publicUrl } } = stitchdb.storage.from('avatars').getPublicUrl(data.path)

Pass { contentType, cacheControl: '3600', upsert } as options. Large files can use resumable uploads (TUS) at /storage/v1/upload/resumable; Studio uses them automatically.

#Download

JavaScript
const { data } = await stitchdb.storage.from('avatars').download('path/avatar.png')

#List, move, copy and delete

JavaScript
const { data: files } = await stitchdb.storage.from('avatars').list('folder', { limit: 100, offset: 0, sortBy: { column: 'name', order: 'asc' } })
await stitchdb.storage.from('avatars').move('old/path.png', 'new/path.png')
await stitchdb.storage.from('avatars').copy('a.png', 'b.png')
await stitchdb.storage.from('avatars').remove(['a.png', 'b.png'])

#Caching and compression

Files in public buckets (/storage/v1/object/public/…) are cached on every server that answers for your project, like a CDN. On a server with a read replica in another region, nearby users get the file from there instead of from your primary server.

  • How long a copy is used follows the file's own Cache-Control. The SDKs upload with max-age=3600 unless you pass cacheControl. A file without Cache-Control is not cached.
  • Expired copies are checked again with the file's ETag, so an unchanged file is not sent again from the primary. If the primary server cannot be reached, the last copy is served.
  • Range requests (for example video seeking) and files of 100 MB or more are not cached.
  • The X-Cache header shows HIT, MISS, REVALIDATED or STALE. After you replace a file under the same name, add a query like ?v=2 to fetch the new one before the old copy expires.
  • Private files, signed URLs and the S3 endpoint are never cached.

Text files over 1 KB (JSON, CSV, plain text, CSS, JavaScript, XML, SVG, wasm, uncompressed fonts) are sent compressed with brotli or gzip when the client asks for it. Images, video, archives, PDF and files that already have a Content-Encoding are sent as they are. Egress counts the bytes that really went out, so compressed files cost less. Cached files still count as egress.

#Limits

Uploads are limited per file by your plan (and by the bucket's own limit if it is lower). While file storage is over its limit, uploads return 413 until files are removed. See Storage limits.

Was this helpful?