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.
storage provides access to your project’s R2 buckets. Import it from edgespark and pass bucket declarations from @defs.
storage.from(bucket)
import { storage } from "edgespark";
import { buckets } from "@defs";
const uploads = storage.from(buckets.uploads);
S3 URI helpers
Use S3 URIs when you want to persist a file reference in your own database:
import { storage } from "edgespark";
import { buckets } from "@defs";
const avatarS3Uri = storage.createS3Uri(buckets.uploads, "avatars/user-1.png");
if (storage.isS3Uri(avatarS3Uri)) {
const parsed = storage.parseS3Uri(avatarS3Uri);
console.log(parsed.bucket.bucket_name, parsed.path);
}
If the input may be invalid, use tryParseS3Uri(...):
const parsed = storage.tryParseS3Uri(inputFromDatabaseOrWebhook);
if (!parsed) {
throw new Error("Invalid S3 URI");
}
Upload and download
import { storage } from "edgespark";
import { buckets } from "@defs";
await storage
.from(buckets.uploads)
.put("reports/q1.pdf", new TextEncoder().encode("report"));
const object = await storage.from(buckets.uploads).get("reports/q1.pdf");
if (!object) throw new Error("Not found");
Use head(...) when you only need metadata:
import { storage } from "edgespark";
import { buckets } from "@defs";
const meta = await storage.from(buckets.uploads).head("reports/q1.pdf");
if (meta) {
console.log(meta.size, meta.contentType);
}
List and delete
import { storage } from "edgespark";
import { buckets } from "@defs";
const files = await storage.from(buckets.uploads).list({ prefix: "reports/" });
await storage.from(buckets.uploads).delete("reports/q1.pdf");
delete(...) also accepts multiple paths:
await storage.from(buckets.uploads).delete([
"reports/q1.pdf",
"reports/q2.pdf",
]);
Paginate or group list results
list(...) supports pagination and delimiter-based grouping:
import { storage } from "edgespark";
import { buckets } from "@defs";
const page = await storage.from(buckets.uploads).list({
prefix: "reports/",
limit: 100,
delimiter: "/",
});
console.log(page.files, page.delimitedPrefixes, page.cursor);
Presigned uploads
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 { uploadUrl, requiredHeaders } = await storage
.from(buckets.uploads)
.createPresignedPutUrl(`user-files/${auth.user.id}/${filename}`, 3600, {
contentType,
});
return c.json({ uploadUrl, requiredHeaders });
});
export default app;
Presigned downloads
import { storage } from "edgespark";
import { Hono } from "hono";
import { buckets } from "@defs";
const app = new Hono().get("/api/download/:key", async (c) => {
const { downloadUrl } = await storage
.from(buckets.uploads)
.createPresignedGetUrl(c.req.param("key"), 3600);
return c.json({ downloadUrl });
});
export default app;
Use presigned URLs for large client uploads and downloads. See platform limits for file size and runtime constraints.
See also
Use storage
Declare buckets, apply them with the CLI, and use storage from your routes.
Build a REST API
Complete example with presigned uploads and file references.