Public/Private
Flexible visibility options
Signed URLs
Time-limited secure access
File Sharing
Grant access to other users
CORS Config
Cross-origin uploads
Public vs Private Files
Files can be either public (anyone can access) or private (requires authentication):
// Public file - accessible to anyone with the URL
const publicFile = await upload(file, {
public: true,
})
// publicFile.url = "https://cdn.sylphx.com/files/abc123.jpg"
// Private file - requires signed URL
const privateFile = await upload(file, {
public: false, // default
})
// privateFile.signedUrl = "https://cdn.sylphx.com/files/abc123.jpg?token=..."
// URL expires after 1 hour by defaultSigned URLs
Generate temporary signed URLs for private files:
import { platform } from '@/lib/platform'
// Get a signed URL that expires in 1 hour (default)
const { url } = await platform.storage.getSignedUrl(fileId)
// Custom expiration (in seconds)
const { url: shortUrl } = await platform.storage.getSignedUrl(fileId, {
expiresIn: 300, // 5 minutes
})
// Long-lived URL (up to 7 days)
const { url: longUrl } = await platform.storage.getSignedUrl(fileId, {
expiresIn: 604800, // 7 days
})URL Security
Download URLs
Generate URLs that force file download instead of browser preview:
const { url } = await platform.storage.getSignedUrl(fileId, {
download: true, // Force download
downloadFilename: 'report.pdf', // Custom filename
})File Permissions
Control who can access private files:
// Set file owner (done automatically on upload)
const file = await platform.storage.upload({
file: buffer,
filename: 'document.pdf',
ownerId: user.id, // Only this user can generate signed URLs
})
// Share with another user
await platform.storage.share(fileId, {
userId: otherUser.id,
permission: 'read', // 'read' or 'write'
})
// Revoke access
await platform.storage.unshare(fileId, {
userId: otherUser.id,
})Change File Visibility
Change a file between public and private:
// Make public
await platform.storage.update(fileId, {
public: true,
})
// Make private
await platform.storage.update(fileId, {
public: false,
})Content-Type Headers
Control how browsers handle files:
// Set content disposition for inline viewing
const { url } = await platform.storage.getSignedUrl(fileId, {
contentDisposition: 'inline', // View in browser
})
// Set content disposition for download
const { url: downloadUrl } = await platform.storage.getSignedUrl(fileId, {
contentDisposition: 'attachment; filename="report.pdf"',
})
// Set cache control
const { url: cachedUrl } = await platform.storage.getSignedUrl(fileId, {
cacheControl: 'public, max-age=3600', // Cache for 1 hour
})CORS Configuration
Configure CORS for client-side uploads:
// In dashboard: App Settings → Storage → CORS
// Example CORS configuration
{
"allowedOrigins": [
"https://myapp.com",
"https://*.myapp.com",
"http://localhost:3000"
],
"allowedMethods": ["GET", "PUT", "POST", "DELETE"],
"allowedHeaders": ["*"],
"maxAge": 3600
}Access Patterns
Common access patterns and when to use them:
| Property | Type | Description |
|---|---|---|
User avatars | Public | public: true |
Product images | Public | public: true |
User documents | Private + Signed URL | getSignedUrl() |
Invoices/receipts | Private + Download | getSignedUrl({ download: true }) |
Shared team files | Private + Sharing | share() |
Security Best Practices
Default to private
Only make files public when necessary
Short-lived URLs
Use short expiration times for signed URLs
Validate uploads
Check file types and sizes before accepting
Scan for malware
Enable virus scanning in dashboard (Pro+)
Audit access
Monitor file access logs in the dashboard