File storage

env.STORAGE is your app's object store for user uploads, generated files, and assets. It's an object-storage bucket with a put/get/list/delete API, and a built-in way to serve files publicly over HTTP.

Reading & writing

// api/upload.js
export default {
  async fetch(request, env, ctx) {
    const user = await env.AUTH.getUser(request);
    if (!user) return new Response("Unauthorized", { status: 401 });

    const body = await request.arrayBuffer();
    const key = user.id + "/avatar.png";

    await env.STORAGE.put(key, body, {
      httpMetadata: { contentType: "image/png" },
    });

    return Response.json({ key });
  },
};
  • put(key, value, opts?) · get(key, opts?) · head(key) · delete(key | key[])
  • list(opts?) — keys are returned relative to your app's space.
  • createMultipartUpload / resumeMultipartUpload for large files.
Keys are scoped to your app automatically — you can't read or overwrite another app's files or the platform's managed objects.

Serving files publicly

Mark an object public when you store it, and it's served at /files/<key> on your app's domain — no route code needed:

await env.STORAGE.put(key, body, {
  httpMetadata: { contentType: "image/png" },
  customMetadata: { public: "true" },
});
// now reachable at  https://your-app.com/files/<key>

Objects without public: "true" aren't served by the /files route — fetch those in your own handler with env.STORAGE.get after an auth check.

Large uploads

For very large user uploads, an assistant can request a direct upload URL with the request_upload_url MCP tool rather than streaming the bytes through a route. See Limits & quotas for file-size caps.