Storage & Files
Manage file uploads, storage, and media processing with the SDK’s comprehensive storage operations. Handle images, videos, audio, and documents with ease.
⚠️ IMPORTANT: Storage operations return
{path, name, mime, size, meta}structure. Use.pathas the unique identifier (NOT.idor.url). Examples below use the correct.pathand.mimefields.
File Uploads
Image Upload
Store user-uploaded images:
.input('profile_photo', 'file', { required: true })
.storageCreateImage(
'$input.profile_photo',
'public',
'uploaded_image'
)
.dbEdit('users',
{ id: '$auth.id' },
{
profile_photo_path: '$uploaded_image.path', // ✅ Use .path
profile_photo_name: '$uploaded_image.name'
},
'updated_user'
)
.response({
image_path: '$uploaded_image.path', // ✅ Correct field
user: '$updated_user'
})
Access levels:
'public'- Publicly accessible URLs'private'- Requires authentication to access
Video Upload
Handle video files with processing options:
.input('video', 'object', { required: true })
.createVideo(
'private',
'$input.video',
'videos/$user.id_$timestamp.mp4',
'uploaded_video',
{
encoding: 'h264',
bitrate: '5000k',
resolution: '1080p'
}
)
.response({
video_id: '$uploaded_video.id',
url: '$uploaded_video.url'
})
Audio Upload
Store audio files:
.input('audio', 'object', { required: true })
.createAudio(
'public',
'$input.audio',
'audio/$user.id_podcast.mp3',
'uploaded_audio'
)
.response({
audio_url: '$uploaded_audio.url',
duration: '$uploaded_audio.duration'
})
Document Upload
Store documents and attachments:
.input('document', 'object', { required: true })
.createAttachment(
'private',
'$input.document',
'documents/$user.id_$filename',
'uploaded_doc'
)
.dbAdd('"documents"', {
user_id: '$auth.id',
file_id: '$uploaded_doc.id',
filename: '$uploaded_doc.filename',
size: '$uploaded_doc.size',
uploaded_at: 'now'
}, 'doc_record')
.response({
document: '$doc_record',
file_url: '$uploaded_doc.url'
})
File Management
Download File from URL
Save external files to your storage:
.input('image_url', 'text', { required: true })
.storageCreateFromUrl(
'$input.image_url',
'imported/$timestamp.jpg',
'downloaded_file'
)
.response({
file_id: '$downloaded_file.id',
local_url: '$downloaded_file.url'
})
Upload File to Path
Upload with specific path and metadata:
.input('file', 'object', { required: true })
.uploadFile(
'$input.file',
'uploads/$auth.id/$filename',
'uploaded',
{
metadata: {
uploaded_by: '$auth.id',
category: '$input.category'
}
}
)
.response({
file: '$uploaded'
})
Download File
Retrieve stored files:
.input('file_id', 'text', { required: true })
.downloadFile('$input.file_id', 'file_data')
.response({
file: '$file_data',
url: '$file_data.url',
size: '$file_data.size'
})
Delete File
Remove files from storage:
.input('file_id', 'text', { required: true })
// Verify ownership
.dbGet('"documents"', { file_id: '$input.file_id' }, 'doc')
.precondition('$doc.user_id == $auth.id', 'Unauthorized')
.deleteFile('$input.file_id', 'deleted')
.dbDelete('"documents"', { file_id: '$input.file_id' }, 'deleted_record')
.response({
deleted: true,
file_id: '$input.file_id'
})
File Operations
List Files
Browse files in a directory:
.input('path', 'text', { default: 'uploads/' })
.listFiles('$input.path', 'files')
.response({
files: '$files',
count: 'count($files)'
})
Get File Metadata
Retrieve file information:
.input('file_id', 'text', { required: true })
.getFileMetadata('$input.file_id', 'metadata')
.response({
filename: '$metadata.filename',
size: '$metadata.size',
type: '$metadata.type',
created: '$metadata.created_at',
modified: '$metadata.modified_at'
})
Move File
Relocate files in storage:
.input('file_id', 'text', { required: true })
.input('new_path', 'text', { required: true })
.moveFile(
'$input.file_id',
'$input.new_path',
'moved_file'
)
.response({
file: '$moved_file',
new_path: '$input.new_path'
})
Copy File
Duplicate files in storage:
.input('file_id', 'text', { required: true })
.input('destination', 'text', { required: true })
.copyFile(
'$input.file_id',
'$input.destination',
'copied_file'
)
.response({
original: '$input.file_id',
copy: '$copied_file'
})
Image Processing
Upload with Transformations
Process images during upload:
.input('image', 'object', { required: true })
.createImage(
'public',
'$input.image',
'processed/$user.id.jpg',
'original_image',
{
resize: {
width: 800,
height: 600,
fit: 'cover'
},
quality: 85,
format: 'jpg'
}
)
.response({
image_url: '$original_image.url',
width: '$original_image.width',
height: '$original_image.height'
})
Create Thumbnails
Generate image thumbnails:
.input('image', 'object', { required: true })
// Upload original
.createImage('public', '$input.image', 'originals/$user.id.jpg', 'original')
// Create thumbnail
.createImage(
'public',
'$original',
'thumbnails/$user.id.jpg',
'thumbnail',
{
resize: {
width: 200,
height: 200,
fit: 'cover'
}
}
)
.response({
original: '$original.url',
thumbnail: '$thumbnail.url'
})
Complete Upload Flow
Profile Photo Upload
Complete example with validation and database storage:
const uploadProfilePhoto = XanoScript.create('users/profile-photo', 'POST')
.description('Upload user profile photo')
.requiresAuth('users')
.input('photo', 'object', { required: true })
// Validate file type
.precondition(
'$input.photo.type contains "image"',
'File must be an image'
)
// Validate file size (5MB max)
.precondition(
'$input.photo.size <= 5242880',
'File size must be under 5MB'
)
// Delete old photo if exists
.dbGet('"users"', { id: '$auth.id' }, 'user')
.conditional('$user.profile_photo_id != null')
.then()
.deleteFile('$user.profile_photo_id', 'deleted_old')
.endConditional()
// Upload new photo
.createImage(
'public',
'$input.photo',
'profiles/$auth.id.jpg',
'new_photo',
{
resize: {
width: 500,
height: 500,
fit: 'cover'
},
quality: 90
}
)
// Create thumbnail
.createImage(
'public',
'$new_photo',
'profiles/thumbs/$auth.id.jpg',
'thumbnail',
{
resize: {
width: 100,
height: 100,
fit: 'cover'
}
}
)
// Update user record
.dbEdit('"users"',
{ id: '$auth.id' },
{
profile_photo_id: '$new_photo.id',
profile_photo_url: '$new_photo.url',
thumbnail_url: '$thumbnail.url',
updated_at: 'now'
},
'updated_user'
)
.response({
photo_url: '$new_photo.url',
thumbnail_url: '$thumbnail.url',
user: {
id: '$updated_user.id',
email: '$updated_user.email',
profile_photo_url: '$updated_user.profile_photo_url'
}
});
Document Management System
Upload and organize documents:
const uploadDocument = XanoScript.create('documents/upload', 'POST')
.description('Upload document with metadata')
.requiresAuth('users')
.input('file', 'object', { required: true })
.input('title', 'text', { required: true })
.input('category', 'text')
.input('tags', 'object')
// Validate file
.precondition(
'$input.file.size <= 10485760',
'File size must be under 10MB'
)
// Upload file
.createAttachment(
'private',
'$input.file',
'documents/$auth.id/$timestamp_$input.file.name',
'uploaded_file'
)
// Create database record
.dbAdd('"documents"', {
user_id: '$auth.id',
file_id: '$uploaded_file.id',
filename: '$uploaded_file.filename',
title: '$input.title',
category: '$input.category',
tags: '$input.tags',
size: '$uploaded_file.size',
type: '$uploaded_file.type',
created_at: 'now'
}, 'doc_record')
.response({
document: {
id: '$doc_record.id',
title: '$doc_record.title',
filename: '$doc_record.filename',
size: '$doc_record.size',
created_at: '$doc_record.created_at'
},
file_url: '$uploaded_file.url'
});
Batch Image Upload
Handle multiple file uploads:
const uploadGallery = XanoScript.create('gallery/upload', 'POST')
.description('Upload multiple images to gallery')
.requiresAuth('users')
.input('images', 'object', { required: true })
.var('uploaded_images', 'array', [])
.forEach('$input.images', '$image')
// Upload image
.createImage(
'public',
'$image',
'gallery/$auth.id/$timestamp_$image.name',
'uploaded'
)
// Create thumbnail
.createImage(
'public',
'$uploaded',
'gallery/thumbs/$auth.id/$timestamp_$image.name',
'thumb',
{
resize: { width: 300, height: 300, fit: 'cover' }
}
)
// Save to database
.dbAdd('"gallery_images"', {
user_id: '$auth.id',
file_id: '$uploaded.id',
url: '$uploaded.url',
thumbnail_url: '$thumb.url',
created_at: 'now'
}, 'image_record')
.arrayPush('$uploaded_images', '$image_record')
.endForEach()
.response({
images: '$uploaded_images',
count: 'count($uploaded_images)'
});
File Validation
Size Limits
Validate file sizes:
.input('file', 'object', { required: true })
.precondition(
'$input.file.size <= 5242880',
'File must be under 5MB'
)
.precondition(
'$input.file.size > 0',
'File is empty'
)
Common size limits:
- 1MB:
1048576 - 5MB:
5242880 - 10MB:
10485760 - 100MB:
104857600
File Type Validation
Restrict allowed file types:
.input('file', 'object', { required: true })
.conditional('$input.file.type contains "image"')
.then()
.createImage('public', '$input.file', 'images/$filename', 'uploaded')
.elseIf('$input.file.type contains "pdf"')
.then()
.createAttachment('private', '$input.file', 'pdfs/$filename', 'uploaded')
.else()
.return({ error: 'Invalid file type' })
.endConditional()
Filename Sanitization
Clean filenames before storage:
.input('file', 'object', { required: true })
.filter('$input.file.name', ['trim', 'lower'], 'clean_name')
.var('safe_filename', 'text', 'replace($clean_name, " ", "_")')
.createAttachment(
'private',
'$input.file',
'uploads/$auth.id/$timestamp_$safe_filename',
'uploaded'
)
Best Practices
Organize by User
Keep user files organized:
'uploads/$auth.id/$category/$timestamp_$filename'
'images/users/$auth.id/$filename'
'documents/$auth.id/$year/$month/$filename'
Use Timestamps
Prevent filename collisions:
.var('timestamp', 'text', 'time()')
.createImage('public', '$file', 'uploads/$timestamp_$filename', 'uploaded')
Clean Up Old Files
Delete orphaned files:
.dbGet('"users"', { id: '$auth.id' }, 'user')
.conditional('$user.old_photo_id != null')
.then()
.deleteFile('$user.old_photo_id', 'deleted')
.endConditional()
Track File Usage
Maintain file metadata:
.dbAdd('"file_usage"', {
user_id: '$auth.id',
file_id: '$uploaded.id',
context: 'profile_photo',
created_at: 'now'
}, 'usage_record')
Secure Private Files
Verify access to private files:
.input('file_id', 'text', { required: true })
.dbGet('"documents"', { file_id: '$input.file_id' }, 'doc')
.precondition('$doc != null', 'File not found')
.precondition('$doc.user_id == $auth.id', 'Access denied')
.downloadFile('$input.file_id', 'file')
Next Steps
- Database Operations - Store file metadata
- Security & Auth - Secure file access
- Recipes - Complete file management examples
- API Reference - Full storage method reference