Documentation Index Fetch the complete documentation index at: https://docs.edgespark.dev/llms.txt
Use this file to discover all available pages before exploring further.
Every EdgeSpark project includes Cloudflare R2 object storage. You declare buckets in server/src/defs/storage_schema.ts, sync them with edgespark storage apply, and use the runtime SDK in your routes.
For browser-facing file transfer, EdgeSpark should usually issue presigned URLs instead of proxying file bytes through your Worker. Use direct put() and get() when the server itself is creating, reading, or transforming the bytes.
Declare buckets
Add bucket definitions to server/src/defs/storage_schema.ts:
server/src/defs/storage_schema.ts
import type { BucketDef } from "@sdk/server-types" ;
export const uploads : BucketDef < "uploads" > = {
bucket_name: "uploads" ,
description: "User-uploaded files" ,
};
export const avatars : BucketDef < "avatars" > = {
bucket_name: "avatars" ,
description: "Profile photos" ,
};
Apply the declarations:
Inspect synced buckets with:
edgespark storage bucket list --desc
Store server-generated content
import { storage } from "edgespark" ;
import { Hono } from "hono" ;
import { buckets } from "@defs" ;
const app = new Hono (). post ( "/api/reports/export" , async ( c ) => {
const csv = [
"id,title" ,
"1,Quarterly report" ,
"2,Annual report" ,
]. join ( " \\ n" );
const path = `reports/export- ${ Date . now () } .csv` ;
await storage . from ( buckets . uploads ). put ( path , new TextEncoder (). encode ( csv ), {
contentType: "text/csv" ,
});
return c . json ({ path }, 201 );
});
export default app ;
Issue a download URL for clients
import { storage } from "edgespark" ;
import { Hono } from "hono" ;
import { buckets } from "@defs" ;
const app = new Hono (). get ( "/api/documents/:filename" , async ( c ) => {
const filename = c . req . param ( "filename" );
const { downloadUrl } = await storage
. from ( buckets . uploads )
. createPresignedGetUrl ( `documents/ ${ filename } ` , 3600 );
return c . json ({ downloadUrl });
});
export default app ;
Read a file server-side
When the server itself needs the bytes, use get() directly:
import { storage } from "edgespark" ;
import { Hono } from "hono" ;
import { buckets } from "@defs" ;
const app = new Hono (). get ( "/api/reports/:filename/raw" , async ( c ) => {
const object = await storage
. from ( buckets . uploads )
. get ( `reports/ ${ c . req . param ( "filename" ) } ` );
if ( ! object ) return c . json ({ error: "Not found" }, 404 );
return new Response ( object . body , {
headers: {
"Content-Type" : object . metadata . contentType ?? "application/octet-stream" ,
},
});
});
export default app ;
List and delete files
import { storage } from "edgespark" ;
import { Hono } from "hono" ;
import { buckets } from "@defs" ;
const app = new Hono ()
. get ( "/api/documents" , async ( c ) => {
const files = await storage . from ( buckets . uploads ). list ({ prefix: "documents/" });
return c . json ( files );
})
. delete ( "/api/documents/:filename" , async ( c ) => {
await storage . from ( buckets . uploads ). delete ( `documents/ ${ c . req . param ( "filename" ) } ` );
return c . body ( null , 204 );
});
export default app ;
Use presigned URLs for direct uploads
For client-originated uploads, generate a presigned URL and upload directly to R2:
import { storage } from "edgespark" ;
import { auth } from "edgespark/http" ;
import { Hono } from "hono" ;
import { buckets } from "@defs" ;
const app = new Hono (). post ( "/api/upload-url" , async ( c ) => {
const { filename , contentType } = await c . req . json <{
filename : string ;
contentType ?: string ;
}>();
const path = `uploads/ ${ auth . user . id } / ${ Date . now () } - ${ filename } ` ;
const { uploadUrl , requiredHeaders } = await storage
. from ( buckets . uploads )
. createPresignedPutUrl ( path , 3600 , {
contentType ,
});
return c . json ({ uploadUrl , requiredHeaders , path });
});
export default app ;
Default to presigned PUT and GET URLs for browser-facing file transfer. When you are working near request, file size, or runtime limits, link back to platform limits .
See also
storage reference Complete storage API: put, get, list, delete, and presigned URLs.
Platform limits File size and runtime constraints for uploads and downloads.