Skip to content

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.

OperationDescription
file.getGet file information and access URLs
file.updateUpdate file permissions and metadata
file.deleteDelete files from storage
file.presign_uploadGenerate secure upload URLs
file.finalize_uploadFinalize file upload
file.report_upload_failureReport failed uploads

Upload Workflow

File uploads use a three-step process for security and reliability:

  1. Presign - Get secure upload credentials
  2. Upload - Upload file to storage using credentials
  3. 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 (public or private)
  • 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, xlarge
    • profilephoto - 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:

VariantMax SizeQualityUse Case
thumbnail150x150px80%Thumbnails, avatars
small300x300px85%Small previews
medium600x600px90%Medium displays
large1200x1200px95%Large displays
xlarge2400x2400px95%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 TypeMaximum Size
Images50 MB
Documents100 MB
Videos500 MB
Audio100 MB
Archives200 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 exist
  • ACCESS_DENIED - Insufficient permissions
  • FILE_TOO_LARGE - File exceeds size limit
  • INVALID_FILE_TYPE - File type not supported
  • UPLOAD_EXPIRED - Presigned URL expired
  • QUOTA_EXCEEDED - Storage quota limit reached
  • PROCESSING_FAILED - Image processing failed