Storage — SDK
The Storage module provides file upload, CDN-backed URLs, metadata management, and file operations (copy, move, delete). Files are stored with global CDN distribution.
What you can build
Section titled “What you can build”- User avatars — Upload profile pictures with automatic CDN URLs
- Document management — Store and organize PDFs, spreadsheets, and text files
- Media galleries — Image and video upload with metadata (dimensions, MIME type)
- File attachments — Attach files to chat messages, support tickets, or form submissions
- Backup exports — Generate and store data export files for users to download
Upload a file
Section titled “Upload a file”const result = await sdk.storage.upload({ file: fileBlob, // File, Blob, or ReadableStream path: 'avatars/user-123.jpg', // Optional custom path contentType: 'image/jpeg', // Optional MIME type})
console.log(result.url) // CDN URL: https://cdn.aerostack.dev/proj_abc123/avatars/user-123.jpgconsole.log(result.key) // Storage key: avatars/user-123.jpgconsole.log(result.size) // File size in bytesconsole.log(result.contentType) // image/jpegresult, err := client.Storage.Upload(ctx, aerostack.UploadInput{ File: reader, Path: "avatars/user-123.jpg", ContentType: "image/jpeg",})// result.URL, result.Key, result.Sizeresult = await client.storage.upload( file_bytes=image_data, path="avatars/user-123.jpg", content_type="image/jpeg")# result.url, result.keyfinal file = File('/path/to/image.jpg');final result = await client.storage.upload( file: file, path: 'avatars/${userId}.jpg', contentType: 'image/jpeg',);final cdnUrl = result.url;Get a file
Section titled “Get a file”Retrieve file content by its storage key:
const file = await sdk.storage.get('avatars/user-123.jpg')// Returns the file contentGet a CDN URL
Section titled “Get a CDN URL”Get a public CDN URL for a stored file without downloading it:
const url = await sdk.storage.getUrl('avatars/user-123.jpg')// https://cdn.aerostack.dev/proj_abc123/avatars/user-123.jpgList files
Section titled “List files”const files = await sdk.storage.list({ prefix: 'avatars/', // Filter by path prefix limit: 50, // Max results})// files: [{ key, size, contentType, lastModified }, ...]Check if a file exists
Section titled “Check if a file exists”const exists = await sdk.storage.exists('avatars/user-123.jpg')// true or falseGet file metadata
Section titled “Get file metadata”const meta = await sdk.storage.getMetadata('avatars/user-123.jpg')// { key, size, contentType, lastModified, etag }Copy a file
Section titled “Copy a file”await sdk.storage.copy('avatars/user-123.jpg', 'backups/user-123.jpg')Move a file
Section titled “Move a file”await sdk.storage.move('uploads/temp-abc.jpg', 'avatars/user-123.jpg')// Original file is deleted after copyDelete a file
Section titled “Delete a file”await sdk.storage.delete('avatars/user-123.jpg')Complete example: avatar upload system
Section titled “Complete example: avatar upload system”import { AerostackClient } from '@aerostack/sdk'
const { sdk } = new AerostackClient({ projectId, apiKey })
async function uploadAvatar(userId: string, file: File) { // 1. Upload the new avatar const result = await sdk.storage.upload({ file, path: `avatars/${userId}.${file.type.split('/')[1]}`, contentType: file.type, })
// 2. Update the user profile with the new URL await sdk.db.query( 'UPDATE users SET avatar_url = ?, updated_at = ? WHERE id = ?', [result.url, Date.now(), userId] )
return result.url}
async function deleteAvatar(userId: string) { // 1. Get current avatar path const user = await sdk.db.queryOne( 'SELECT avatar_url FROM users WHERE id = ?', [userId] )
if (user?.avatar_url) { // 2. Extract key from URL and delete const key = user.avatar_url.split('/').slice(-2).join('/') await sdk.storage.delete(key) }
// 3. Clear the profile await sdk.db.query( 'UPDATE users SET avatar_url = NULL, updated_at = ? WHERE id = ?', [Date.now(), userId] )}Complete example: document manager
Section titled “Complete example: document manager”async function uploadDocument(userId: string, file: File, folder: string) { const id = crypto.randomUUID() const ext = file.name.split('.').pop()
// Upload to storage const result = await sdk.storage.upload({ file, path: `documents/${userId}/${folder}/${id}.${ext}`, contentType: file.type, })
// Record in database const { results: [doc] } = await sdk.db.query( `INSERT INTO documents (id, user_id, folder, filename, storage_key, url, size, content_type, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`, [id, userId, folder, file.name, result.key, result.url, result.size, result.contentType, Date.now()] )
return doc}
async function listDocuments(userId: string, folder: string) { const { results } = await sdk.db.query( 'SELECT * FROM documents WHERE user_id = ? AND folder = ? ORDER BY created_at DESC', [userId, folder] ) return results}API reference
Section titled “API reference”| Method | Signature | Returns |
|---|---|---|
sdk.storage.upload | (opts: { file, path?, contentType? }) => Promise<UploadResult> | { url, key, size, contentType } |
sdk.storage.get | (key: string) => Promise<any> | File content |
sdk.storage.getUrl | (key: string) => Promise<string> | CDN URL |
sdk.storage.list | (opts?: { prefix?, limit? }) => Promise<FileInfo[]> | Array of file info |
sdk.storage.delete | (key: string) => Promise<void> | Nothing |
sdk.storage.exists | (key: string) => Promise<boolean> | Boolean |
sdk.storage.getMetadata | (key: string) => Promise<FileMetadata> | Metadata object |
sdk.storage.copy | (source: string, dest: string) => Promise<void> | Nothing |
sdk.storage.move | (source: string, dest: string) => Promise<void> | Nothing |