req.env.R2 in every handler. Whether you need to accept file uploads, serve assets, or build a private document store, R2 fits naturally into any Blaze route — no SDK to initialize, no credentials to manage beyond your wrangler.toml binding.
Configure the binding
1
Add the bucket to wrangler.toml
wrangler.toml
2
Define the Env type
src/types/env.ts
3
Pass Env to createApp
src/index.ts
Uploading a file
Read the raw request body withreq.arrayBuffer(), then call req.env.R2.put(key, body, options). Pass httpMetadata to preserve the content type and customMetadata to store any application-level attributes alongside the object.
R2 objects are limited to 5 TB per object. For uploads larger than a few
hundred MB, consider using R2’s multipart upload API via a presigned URL so
the client streams directly to R2 instead of buffering through your Worker.
Downloading a file
req.env.R2.get(key) returns an R2ObjectBody when the object exists or null when it does not. Always check for null before accessing the body, then forward the content type and ETag headers before streaming the response.
Listing objects
req.env.R2.list() returns the first page of objects in the bucket. Use the prefix option to scope results to a virtual directory and cursor to paginate through large buckets.
Deleting objects
req.env.R2.delete(key) removes a single object. Deleting a key that does not exist is a no-op — R2 returns success regardless.
Metadata and ETags
Every R2 object exposeshttpMetadata (standard HTTP headers stored at upload time) and httpEtag (a content fingerprint). Use these to power proper browser caching without any extra computation in your Worker.
ETag header and let Blaze’s etag middleware handle If-None-Match negotiation automatically, returning a 304 Not Modified when the client already holds a fresh copy: