Skip to content
sproutboat
Esc
navigateopen⌘Jpreview
On this page

R2 (object storage)

Object storage bound to env.NAME. Bytes live in their own file, never inline in a database row.

Configuration

"r2_buckets": ["MEDIA"]

Usage

env.MEDIA.put("path/file.txt", body, { httpMetadata: { contentType: "text/plain" } });
const obj = env.MEDIA.get("path/file.txt");   // obj.body, obj.size, obj.etag, obj.uploaded  (or null)
obj.toResponse();                             // serves obj.body byte for byte -- use this for
                                               // binary content, not new Response(obj.body), which
                                               // re-encodes it as text and corrupts anything non-ASCII
env.MEDIA.head("path/file.txt");
env.MEDIA.delete("path/file.txt");
const { objects, truncated, cursor } = env.MEDIA.list({ prefix: "path/", limit: 100 });

Methods

Method Signature Returns
put (key, body, { httpMetadata? })
get (key) an object with .body, .size, .etag, .uploaded, and .toResponse() — or null
head (key) metadata without the body
delete (key)
list ({ prefix?, limit?, cursor? }) { objects, truncated, cursor }

An object’s bytes live in their own file (r2-blobs/<hash-of-bucket-and-key>.blob next to the bucket’s metadata), never inline in a database row or the request frame — one write, one read, no extra copy on top. Binary objects round-trip byte for byte on both paths.

Memory and size limits

Two limits keep this bounded by default:

  • Inbound request bodies over 1 MiB (SB_REQUEST_BODY_MAX) are refused, so an upload cannot exceed that unless an operator raises it.
  • Outbound fetch() refuses a response body over 32 MiB (SB_FETCH_MAX_BYTES).

True streaming put/get needs Porffor’s own ReadableStream support, which it does not have yet (porffor#349).

Was this page helpful?