This feature is in beta. Core behavior is stable and ready to try, but some APIs or configuration may still evolve before general availability.
Storage
EdgeBase Storage provides file storage built on Cloudflare R2 with $0 egress fees. Upload and download files with per-bucket access rules, generate time-limited signed URLs for secure sharing without authentication, and handle large files with resumable multipart uploads. Attach custom metadata to any file and control access with auth-aware read, write, and delete rules.
R2 must be enabled in the Cloudflare Dashboard before deploying: R2 Object Storage → Get Started. R2 includes 10 GB of free usage with $0 egress, but Cloudflare still requires a one-time R2 subscription / billing activation before first use.
- Access Rules: Storage Access Rules gate bucket reads, uploads, and deletes.
- Hooks: Storage Hooks validate uploads, restrict downloads, and run file lifecycle side effects.
- Triggers: Storage is not a trigger-based surface.
- Handlers: Inline storage behavior lives under
storage.buckets[name].handlers.hooksinedgebase.config.ts.
Features
Upload / Download
Simple file operations with per-bucket access rules
Signed URLs
Time-limited access links for secure sharing (no auth required)
Multipart Upload
Resume-capable uploads for large files (state tracked via KV)
Metadata
Attach custom key-value metadata to any file
Access Rules
Per-bucket read, write, delete rules with auth context
Storage Hooks
Validate uploads, restrict downloads, and run post-upload or delete side effects
Quick Example
Assume client is already initialized with your platform SDK.
- JavaScript
- Dart/Flutter
- Swift
- Kotlin
- Java
- C#
- C++
const result = await client.storage.bucket('photos').upload('photo-001.jpg', file, {
customMetadata: { uploadedBy: currentUser.id },
});
const url = client.storage.bucket('photos').getUrl('photo-001.jpg');
const blob = await client.storage.bucket('photos').download('photo-001.jpg');
final bucket = client.storage.bucket('photos');
await bucket.upload(
'photo-001.jpg',
fileBytes,
contentType: 'image/jpeg',
customMetadata: {'uploadedBy': currentUser.id},
);
final url = bucket.getUrl('photo-001.jpg');
final bytes = await bucket.download('photo-001.jpg');
let bucket = client.storage.bucket("photos")
try await bucket.upload(
"photo-001.jpg",
data: imageData,
contentType: "image/jpeg",
customMetadata: ["uploadedBy": currentUser["id"] ?? ""]
)
let url = bucket.getUrl("photo-001.jpg")
let data = try await bucket.download("photo-001.jpg")
val bucket = client.storage.bucket("photos")
bucket.upload(
"photo-001.jpg",
fileBytes,
"image/jpeg",
mapOf("uploadedBy" to currentUserId)
)
val url = bucket.getUrl("photo-001.jpg")
val bytes = bucket.download("photo-001.jpg")
StorageBucket bucket = client.storage().bucket("photos");
bucket.upload("photo-001.jpg", fileBytes, "image/jpeg");
String url = bucket.getUrl("photo-001.jpg");
byte[] bytes = bucket.download("photo-001.jpg");
var bucket = client.Storage.Bucket("photos");
await bucket.UploadAsync("photo-001.jpg", fileBytes, "image/jpeg", new() {
["uploadedBy"] = currentUserId,
});
var url = bucket.GetUrl("photo-001.jpg");
var bytes = await bucket.DownloadAsync("photo-001.jpg");
auto bucket = client.storage().bucket("photos");
bucket.upload("photo-001.jpg", data, "image/jpeg");
std::string url = bucket.getUrl("photo-001.jpg");
auto bytes = bucket.download("photo-001.jpg");
// Signed URL (no auth needed to access)
const signedUrl = await admin.storage.bucket('photos').createSignedUrl('photo-001.jpg', {
expiresIn: '1h',
});
Server-side storage operations such as signed URL generation and privileged file access are available across all Admin SDKs.
Access Rules
// edgebase.config.ts
storage: {
buckets: {
photos: {
access: {
read() { return true }, // Public read
write(auth) { return auth !== null }, // Auth required
delete(auth, file) { return auth !== null && auth.id === file.uploadedBy },
},
},
},
}
Next Steps
Basic file operations, SDK usage
Time-limited access for secure file sharing
Resumable uploads for large files
Custom metadata on files
Per-bucket read, write, and delete control
Validate uploads and run lifecycle side effects
Choose Client SDK vs Admin SDK for storage workflows