Storage
Easily set up file storage in your app with Cloudflare R2 or S3-compatible services to handle uploads, downloads, deletions, and public file access.
Tools
- Cloudflare R2 – simple and cost-effective storage (recommended)
- AWS S3 (or any S3-compatible service) – more advanced features
Setup
- Choose a storage provider:
- Cloudflare R2 – recommended for simplicity and low cost
- AWS S3 (or compatible services like MinIO, DigitalOcean Spaces, etc.)
- Create a bucket:
- Go to your provider’s dashboard and create a new bucket (folder for files)
- Copy the credentials: access key, secret key, bucket name, endpoint
- Cloudflare R2 specific steps:
- Sign up / Sign in at Cloudflare
- Create a new R2 bucket:
- Pick a globally unique bucket name (e.g.,
your-project-name) - Select a region close to your target audience
- Pick a globally unique bucket name (e.g.,
- Enable public access: Settings → Public Development URL → Enable
- Save the public URL as
STORAGE_PUBLIC_URL - Optional: Set custom domains for added security
- Save the public URL as
- Create a new API Token:
- Storage & databases > R2 object storage > API Tokens > Manage, click Create User API Token
- Set permissions to Object Read & Write to the bucket
- Copy the Access Key ID and Secret Access Key
- Set the following environment variables:.env
S3_REGION="your-region" # Use "auto" for R2, or e.g. "us-east-1" for S3 S3_BUCKET="your-bucket-name" S3_ACCESS_KEY_ID="your-access-key-id" S3_SECRET_ACCESS_KEY="your-secret-access-key" S3_ENDPOINT="your-s3-endpoint" # Optional S3_PUBLIC_URL="https://cdn.yourdomain.com" # Public URL (CDN or subdomain)
Usage
Storage functions are available in the File Management module in the Admin Panel. Use the useApi composable:
- List files:app/pages/admin/files.vue
const { getStorageFiles } = useApi(); const response = await getStorageFiles(); console.log('File uploaded list:', response.data.blobs); - Upload files:app/pages/admin/files.vue
const { uploadStorageFiles } = useApi(); const selectedFiles = ref<File[]>([]); const response = await uploadStorageFiles(selectedFiles.value); console.log('File uploaded total:', response.data.success); - Download a File:app/pages/admin/files.vue
const { downloadStorageFile } = useApi(); const file = await downloadStorageFile('example.jpg'); - Delete a File:app/pages/admin/files.vue
const { deleteStorageFile } = useApi(); const response = await deleteStorageFile('example.jpg'); console.log('Deleted?', response.success); - Bulk delete files:app/pages/admin/files.vue
const { bulkDeleteStorageFile } = useApi(); const response = await bulkDeleteStorageFile(['example.jpg']); console.log('Deleted Total: ', response.data.success); - Access public file (CDN):app/pages/admin/files.vue
const { public: pub } = useRuntimeConfig(); const imageUrl = `${pub.storagePublicUrl}/example.jpg`; console.log(imageUrl); // https://cdn.yourdomain.com/example.jpg
Best Practices
- File Size Limits: Set reasonable file size limits to prevent abuse
- File Type Validation: Validate file types on both client and server sides for security