Overview
File upload features:- JSON Schema validation - Enforce file types and constraints
- Object storage - Local filesystem or S3-compatible storage
- Automatic cleanup - Orphaned files are deleted
- Content type detection - MIME type inference
- Record API integration - Upload files as part of record creation/updates
- Access control - Files inherit record permissions
Basic File Upload
1. Define Schema
Add a file upload column to your table:migrations/main/U1234567890__add_avatar_to_profiles.sql
File Upload Schema:
std.FileUpload- Single filestd.FileUploads- Multiple files (array)- Second parameter: column name
- Third parameter (optional): allowed MIME types
2. Upload File from Client
- TypeScript
- React
- Dart/Flutter
- cURL
3. Access Uploaded Files
Files are automatically stored and accessible via the Record API:File Upload Schema
Single File Upload
Multiple File Uploads
Mixed Content
Combine different file types:File Metadata
TheFileUpload type contains:
Always use
mime_type for validation, not content_type. The mime_type is inferred by TrailBase and cannot be spoofed by clients.Accessing Files
Download File
Files are served via the Record API:Direct URL Construction
For convenience, construct URLs directly:Updating Files
Replace File
Remove File
TrailBase automatically deletes orphaned files. When you replace or remove a file, the old file is queued for deletion.
File Storage
Local Filesystem
By default, files are stored intraildepot/uploads/:
S3-Compatible Storage
Configure S3 or compatible storage (MinIO, DigitalOcean Spaces, etc.):Access Control
File access inherits record permissions:traildepot/config.textproto
- Anyone can view profile avatars (world-readable)
- Only the profile owner can upload/change their avatar
Private Files
traildepot/config.textproto
Validation
File Type Constraints
Restrict file types using MIME type patterns:Client-Side Validation
Real-World Example: Blog with Images
From the Blog Example:migrations/main/U1725019362__create_articles.sql
Image Optimization
Client-Side Resizing
Resize images before upload to reduce bandwidth:WASM Image Processing
Process images server-side using WASM:Cleanup
Automatic Cleanup
TrailBase automatically deletes orphaned files:- When a record is deleted, files are queued for deletion
- When a file column is updated, the old file is queued
- A background job processes the deletion queue
Manual Cleanup
Query pending deletions:Best Practices
1
Validate File Types
Always specify allowed MIME types in your schema:
2
Limit File Sizes
Implement client-side size limits:
3
Use Descriptive Column Names
Name columns based on their purpose:
4
Optimize Images
Resize large images before upload:
- Reduce dimensions to reasonable sizes (e.g., 1200x1200)
- Compress quality for web delivery
- Consider WebP format for better compression
5
Use CDN for Production
Serve files through a CDN for better performance:
- Configure S3 with CloudFront
- Use custom domain for files
- Enable caching headers
Troubleshooting
File Upload Fails
Symptom: Upload returns 400 error Solutions:- Check MIME type constraints in schema
- Verify file is not corrupted
- Check request
Content-Typeismultipart/form-data - Ensure file size is within limits
File Not Found
Symptom: File URL returns 404 Solutions:- Verify record exists and contains file metadata
- Check file column is not NULL
- Verify
filenamematches exactly - Check access permissions
Files Not Deleted
Symptom: Old files remain after update/delete Solutions:- Check
_file_deletionstable for pending deletions - Wait for background cleanup job (runs periodically)
- Verify object storage credentials are correct
Next Steps
First App
Build an app with file uploads
Database Setup
Learn about file upload schemas
Authentication
Secure file uploads
WASM Runtime
Process files with WebAssembly
Examples
- Blog Example - Articles with featured images
- User Avatars - Profile avatars with authentication