Files
Overview
Files - Secure file upload and management system with automatic image processing, permission control, and metadata management. Supports the complete file lifecycle from upload to deletion.
Operations
An operation is an action performed for file management. All operations require the op property to specify which operation to perform.
| Operation | Description |
|---|---|
file.get | Get file information and access URLs |
file.update | Update file permissions and metadata |
file.delete | Delete files from storage |
file.presign_upload | Generate secure upload URLs |
file.finalize_upload | Finalize file upload |
file.report_upload_failure | Report failed uploads |
Upload Workflow
File uploads use a three-step process for security and reliability:
- Presign - Get secure upload credentials
- Upload - Upload file to storage using credentials
- Finalize - Finalize and process the uploaded file
Get File Info
file.get
Retrieve file information and access URLs.
Public file:
json
{
"op": "file.get",
"_key": "file_abc123"
}Private file with temporary access:
json
{
"op": "file.get",
"_key": "file_private456",
"signed_ttl": 3600
}Parameters:
- _key (required) - File identifier
- signed_ttl (optional) - Temporary access duration in seconds for private files (max: 604800 = 7 days)
Response:
json
{
"data": {
"_key": "file_abc123",
"url": "https://storage.example.com/files/report.pdf",
"filename": "report.pdf",
"filesize": "2048576",
"filetype": "document",
"content_type": "application/pdf",
"acl": "private",
"metata": {
"category": "reports",
"department": "Finance",
"uploaded_by": "user_123",
"upload_date": "2024-01-15T10:30:00Z"
},
"image_variants": {}
}
}Response fields:
- _key - Unique file identifier
- url - Direct access URL (signed for private files)
- filename - Original filename
- filesize - File size in bytes
- filetype - File category (
image,document,video, etc.) - content_type - MIME type
- acl - Access control (
publicorprivate) - metadata - Custom metadata
- image_variants - Available image sizes (for images only)
Update File
file.update
Update file permissions and metadata.
Make file public:
json
{
"op": "file.update",
"_key": "file_abc123",
"public_read": true
}Update metadata:
json
{
"op": "file.update",
"_key": "file_abc123",
"metadata": {
"description": "Updated financial report",
"tags": ["Q1", "2024", "revenue"],
"status": "approved"
}
}Update both:
json
{
"op": "file.update",
"_key": "file_abc123",
"public_read": false,
"metadata": {
"classification": "confidential",
"retention_policy": "7_years"
}
}Parameters:
- _key (required) - File identifier
- public_read (optional) - Set visibility (
true= public,false= private) - metadata (optional) - Custom metadata object
Response:
json
{
"data": {
"_key": "file_abc123",
"change": "updated"
}
}Delete File
file.delete
Permanently delete files from storage.
json
{
"op": "file.delete",
"_key": "file_abc123"
}Parameters:
- _key (required) - File identifier to delete
Response:
json
{
"data": {
"_key": "file_abc123",
"change": "deleted"
}
}Presign Upload
file.presign_upload
Generate secure presigned URLs for file uploads.
Basic document upload:
json
{
"op": "file.presign_upload",
"filename": "report.pdf",
"content_type": "application/pdf",
"public_read": false,
"metadata": {
"category": "reports",
"department": "Finance"
}
}Image upload with variants:
json
{
"op": "file.presign_upload",
"filename": "photo.jpg",
"content_type": "image/jpeg",
"public_read": true,
"options": {
"variants": ["thumbnail", "medium", "large"]
}
}Profile photo upload:
json
{
"op": "file.presign_upload",
"filename": "avatar.jpg",
"content_type": "image/jpeg",
"public_read": true,
"options": {
"profilephoto": true,
"variants": ["thumbnail", "medium"]
}
}Parameters:
- filename (required) - Original filename with extension
- content_type (required) - MIME type (e.g.,
image/jpeg,application/pdf) - public_read (optional) - File visibility (
true= public,false= private) - new_name (optional) - Custom filename for storage
- metadata (optional) - Custom data to store with file
- options (optional):
variants- Image sizes to generate:thumbnail,small,medium,large,xlargeprofilephoto- Enable profile photo optimization
Response:
json
{
"data": {
"info": {
"_key": "file_abc123",
"filename": "report.pdf",
"fileclass": "document",
"content_type": "application/pdf",
"acl": "private"
},
"presigned_data": {
"url": "https://storage.amazonaws.com/bucket",
"fields": {
"key": "uploads/2024/01/report.pdf",
"AWSAccessKeyId": "AKIAIOSFODNN7EXAMPLE",
"policy": "eyJleHBpcmF0aW9uIjoi...",
"signature": "signature-hash"
}
}
}
}Upload to Storage
Use the presigned data to upload the file directly to storage:
javascript
// Get presigned data from file.presign_upload response
const { info, presigned_data } = response.data;
// Create form data with presigned fields
const formData = new FormData();
Object.entries(presigned_data.fields).forEach(([key, value]) => {
formData.append(key, value);
});
formData.append('file', fileBlob);
// Upload file
await fetch(presigned_data.url, {
method: 'POST',
body: formData
});Finalize Upload
file.finalize_upload
Finalize the upload and complete file processing.
json
{
"op": "file.finalize_upload",
"_key": "file_abc123",
"presigned_data": {
"url": "https://storage.amazonaws.com/bucket",
"fields": {
"key": "uploads/2024/01/report.pdf"
}
}
}Parameters:
- _key (required) - File key from presign response
- presigned_data (required) - Presigned data from presign response
Response:
json
{
"data": {
"_key": "file_abc123",
"url": "https://storage.example.com/uploads/2024/01/report.pdf",
"filename": "report.pdf",
"filesize": "2048576",
"fileclass": "document",
"content_type": "application/pdf",
"acl": "private",
"image_variants": {}
}
}For images with variants, the response includes generated sizes:
json
{
"data": {
"_key": "image_789",
"url": "https://storage.example.com/images/photo.jpg",
"image_variants": {
"thumbnail": "https://storage.example.com/images/photo_thumb.jpg",
"medium": "https://storage.example.com/images/photo_medium.jpg",
"large": "https://storage.example.com/images/photo_large.jpg"
}
}
}Report Upload Failure
file.report_upload_failure
Report failed upload attempts for cleanup and debugging.
json
{
"op": "file.report_upload_failure",
"_key": "file_failed123",
"presigned_data": {
"url": "https://storage.amazonaws.com/bucket",
"fields": {
"key": "uploads/2024/01/failed.pdf"
}
},
"errors": {
"error_code": "NETWORK_TIMEOUT",
"message": "Upload failed due to network timeout"
}
}Parameters:
- _key (required) - File key from failed upload
- presigned_data (required) - Original presigned data
- errors (required) - Error details (object or string)
Complete Upload Example
javascript
async function uploadFile(file, options = {}) {
try {
// Step 1: Presign upload
const presignResponse = await fetch('https://cloud.singlebaseapis.com/api/<ENDPOINT_KEY>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': 'your_api_key',
'Authorization': 'Bearer your_jwt_token'
},
body: JSON.stringify({
op: 'file.presign_upload',
filename: file.name,
content_type: file.type,
public_read: options.public || false,
metadata: options.metadata || {},
options: options.uploadOptions || {}
})
});
const { info, presigned_data } = presignResponse.data;
// Step 2: Upload to storage - Update the form data
const formData = new FormData();
Object.entries(presigned_data.fields).forEach(([key, value]) => {
formData.append(key, value);
});
formData.append('file', file);
const uploadResponse = await fetch(presigned_data.url, {
method: 'POST',
body: formData
});
// upload failed, abort
if (!uploadResponse.ok) {
// Report error
await fetch('https://cloud.singlebaseapis.com/api/<ENDPOINT_KEY>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': 'your_api_key',
'Authorization': 'Bearer your_jwt_token'
},
body: JSON.stringify({
op: 'file.report_upload_failure',
_key: info._key,
presigned_data: presigned_data,
errors: { error_code: 'UPLOAD_FAILED', message: 'Upload failed' }
})
});
throw new Error('Upload failed');
}
// Step 3: Finalize upload
const finalizeResponse = await fetch('https://cloud.singlebaseapis.com/api/<ENDPOINT_KEY>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': 'your_api_key',
'Authorization': 'Bearer your_jwt_token'
},
body: JSON.stringify({
op: 'file.finalize_upload',
_key: info._key,
presigned_data: presigned_data
})
});
return finalizeResponse.data;
} catch (error) {
console.error('Upload failed:', error);
throw error;
}
}
// Usage
const fileInput = document.getElementById('file-input');
const file = fileInput.files[0];
uploadFile(file, {
public: true,
metadata: {
category: 'user-content',
uploaded_by: 'user_123'
},
uploadOptions: {
variants: ['thumbnail', 'medium']
}
}).then(result => {
console.log('Upload successful:', result);
console.log('File URL:', result.url);
}).catch(error => {
console.error('Upload error:', error);
});Image Processing
Image Variants
When uploading images, automatically generate different sizes:
| Variant | Max Size | Quality | Use Case |
|---|---|---|---|
thumbnail | 150x150px | 80% | Thumbnails, avatars |
small | 300x300px | 85% | Small previews |
medium | 600x600px | 90% | Medium displays |
large | 1200x1200px | 95% | Large displays |
xlarge | 2400x2400px | 95% | Full resolution |
Example:
json
{
"op": "file.presign_upload",
"filename": "product.jpg",
"content_type": "image/jpeg",
"public_read": true,
"options": {
"variants": ["thumbnail", "medium", "large"]
}
}Profile Photos
Profile photo uploads receive special processing:
- Square cropping from center
- Face detection and centering (when available)
- Optimized compression for web
json
{
"op": "file.presign_upload",
"filename": "avatar.jpg",
"content_type": "image/jpeg",
"public_read": true,
"options": {
"profilephoto": true,
"variants": ["thumbnail", "medium"]
}
}File Size Limits
| File Type | Maximum Size |
|---|---|
| Images | 50 MB |
| Documents | 100 MB |
| Videos | 500 MB |
| Audio | 100 MB |
| Archives | 200 MB |
Common Patterns
Batch Upload
javascript
async function batchUpload(files, commonMetadata = {}) {
const results = [];
for (const file of files) {
try {
const result = await uploadFile(file, {
metadata: {
...commonMetadata,
original_name: file.name,
file_index: results.length
}
});
results.push({ success: true, file: result });
} catch (error) {
results.push({ success: false, filename: file.name, error: error.message });
}
}
return results;
}Temporary File Cleanup
javascript
async function cleanupOldFiles(fileKeys, maxAgeHours = 24) {
const cutoffTime = Date.now() - (maxAgeHours * 60 * 60 * 1000);
for (const fileKey of fileKeys) {
try {
const info = await getFileInfo(fileKey);
const uploadTime = new Date(info.data.info.upload_date).getTime();
if (uploadTime < cutoffTime) {
await deleteFile(fileKey);
}
} catch (error) {
console.error(`Failed to cleanup ${fileKey}:`, error);
}
}
}Error Handling
json
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error description"
}
}Common error codes:
FILE_NOT_FOUND- File doesn't existACCESS_DENIED- Insufficient permissionsFILE_TOO_LARGE- File exceeds size limitINVALID_FILE_TYPE- File type not supportedUPLOAD_EXPIRED- Presigned URL expiredQUOTA_EXCEEDED- Storage quota limit reachedPROCESSING_FAILED- Image processing failed