File operations
Upload, download, list, and delete files using the EmuView SDK with the presigned R2 URL flow.
#File operations
The EmuView SDK handles file uploads, downloads, listing, and deletion. Behind the scenes, uploads use a three-step presigned URL flow — files go directly from the browser to Cloudflare R2 without passing through the Worker.
#Prerequisites
- An EmuView SDK instance configured with authentication
- For uploads: an authenticated user with
system/files:createpermission
import { EmuView } from '@emuview/sdk';
const sdk = new EmuView({
url: 'https://your-api.example.com',
auth: { apiKey: 'sk-your-api-key' }
});
#Steps
#1. Upload a file
The sdk.files.upload() method wraps the full presigned URL flow into a single call:
const fileInput = document.querySelector('input[type=file]');
const file = fileInput.files[0];
const { fileId } = await sdk.files.upload(file, {
filename: file.name,
mimeType: file.type,
collection: 'products' // optional: associate with a collection
});
console.log(`Uploaded file: ${fileId}`);
After uploading, store the fileId in a record's file field:
await sdk.collection('products').update('b10b01964f804a55b140be7dad738c8f', {
image: fileId
});
The SDK handles all three steps (request token, PUT to R2, confirm upload) automatically. For custom upload flows, use the Files API endpoints directly.
#2. Download a file
Get a presigned download URL for a file. The URL expires after 5 minutes.
const downloadUrl = await sdk.files.getDownloadUrl('file_a1b2c3d4e5f6a7b8');
// Use the URL in an <img> tag, <a> download link, or fetch()
const img = document.createElement('img');
img.src = downloadUrl;
Request a thumbnail variant for images:
const thumbUrl = await sdk.files.getDownloadUrl('file_a1b2c3d4e5f6a7b8', {
size: 'thumbnail'
});
#3. List all files
Retrieve all completed files in the current project:
const files = await sdk.files.list();
for (const file of files) {
console.log(`${file.filename} (${file.mimeType}, ${file.sizeBytes} bytes)`);
}
The response includes metadata for each file:
// Each file object:
{
id: 'file_a1b2c3d4e5f6a7b8',
filename: 'product-photo.jpg',
mimeType: 'image/jpeg',
sizeBytes: 2048576,
collectionName: 'products',
uploadedBy: 'usr_01HXK5M9ABCDEF',
createdAt: 1718900000,
}
#4. Delete a file
Delete a file, its thumbnails, and metadata:
await sdk.files.delete('file_a1b2c3d4e5f6a7b8');
Deletion is permanent. The original file, all size variants (thumbnails), and the database record are removed.
#What you learned
- How to upload files with a single SDK call
- How to get presigned download URLs (with optional size variants)
- How to list and delete files
#Next steps
- Files API — raw HTTP endpoints for custom upload flows
- Collections — store file IDs in record fields using the
filefield type
#Error handling
File operations throw ApiError on failure:
import { ApiError } from '@emuview/sdk';
try {
await sdk.files.upload(largeFile, {
filename: 'backup.zip',
mimeType: 'application/zip'
});
} catch (err) {
if (err instanceof ApiError) {
if (err.code === 'limit_exceeded') {
console.error('File exceeds project storage quota (5 GB default)');
}
}
}
#Common errors
| Code | Status | Cause |
|---|---|---|
limit_exceeded |
400 | File size exceeds project storage quota |
forbidden |
403 | User lacks file upload/download/delete permission |
not_found |
404 | File ID does not exist or upload was not confirmed |
#Storage limits
| Limit | Default |
|---|---|
| Project storage quota | 5 GB |
| Max upload size | 100 MB per file |
| Upload URL expiry | 120 seconds |
| Download URL expiry | 300 seconds (5 minutes) |