惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Jina AI
Jina AI
雷峰网
雷峰网
The Register - Security
The Register - Security
The Cloudflare Blog
博客园 - 【当耐特】
M
MIT News - Artificial intelligence
I
InfoQ
博客园 - 三生石上(FineUI控件)
H
Help Net Security
博客园 - 司徒正美
Vercel News
Vercel News
WordPress大学
WordPress大学
S
SegmentFault 最新的问题
云风的 BLOG
云风的 BLOG
B
Blog
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
L
LangChain Blog
人人都是产品经理
人人都是产品经理
GbyAI
GbyAI
T
The Blog of Author Tim Ferriss
T
Tailwind CSS Blog
aimingoo的专栏
aimingoo的专栏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Recorded Future
Recorded Future
小众软件
小众软件
Martin Fowler
Martin Fowler
罗磊的独立博客
Stack Overflow Blog
Stack Overflow Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
酷 壳 – CoolShell
酷 壳 – CoolShell
腾讯CDC
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Apple Machine Learning Research
Apple Machine Learning Research
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - Franky
Hugging Face - Blog
Hugging Face - Blog
Y
Y Combinator Blog
V
Visual Studio Blog
F
Fortinet All Blogs
Microsoft Azure Blog
Microsoft Azure Blog
大猫的无限游戏
大猫的无限游戏
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
V
V2EX
Blog — PlanetScale
Blog — PlanetScale

Flavio Copes

Workers Cache: a cache in front of your Cloudflare Worker Cloudflare Drop: drag a folder, get a live site Temporary Cloudflare accounts: agents can now deploy without signing up Moondream 3.1 on Workers AI: fast vision at the edge inferencecost.dev: what will AI inference cost you at 10k users? Sitebase: all the features your website needs, in one place StackPlan: figure out where to deploy your app, and what it How the Cloudflare Pages build cache works The Summer of Code How I generate an Open Graph image for every post New: 90 free tools for developers How I added search to my static site with Pagefind How to rebuild a Cloudflare site on a schedule Cloudflare Email Workers: run code when an email arrives Cloudflare Turnstile: stop bots without annoying CAPTCHAs Cloudflare Workers: secrets and environments Cloudflare Workers observability: logs and traces Cloudflare Analytics Engine: store and query metrics The AI Workshop (July 2026 cohort) Cloudflare Cron Triggers: run a Worker on a schedule Cloudflare Durable Objects: state that lives in one place Cloudflare Queues: run work in the background Cloudflare KV: a key-value store for your Workers Cloudflare D1: a SQL database for your Workers Serving a website with Cloudflare Workers static assets Wrangler: the Cloudflare Workers command line tool Executor: one gateway to connect your AI agent to every tool Cloudflare Workers: your first serverless function Vercel eve: an open framework for building AI agents Flue: the open framework for building AI agents Val Town: write and deploy code in seconds A hands-on guide to The Agency, a collection of AI agents The AI Workshop (June 2026 cohort) The AI Workshop (May 2026 cohort) The AI Workshop (Apr 2026 cohort)
Cloudflare R2: object storage without egress fees
Flavio Copes · 2026-06-25 · via Flavio Copes

By Flavio Copes

How to store and serve files like images and uploads with Cloudflare R2 from a Worker. S3-compatible storage with no egress fees.

~~~

When users upload a photo, or you generate a PDF, you need somewhere to put the file. On Cloudflare, that’s R2.

R2 is object storage. You store files, called objects, in a bucket, and read them back later. If you’ve used Amazon S3, it’s the same idea, and it’s even S3-compatible.

The big difference is the price. With most providers you pay every time someone downloads a file (that’s “egress”). R2 has no egress fees. If you serve a lot of files, that adds up fast.

Let’s use it.

By the way, if you’re unsure whether your data belongs in R2, KV, D1 or Durable Objects, I built a free Cloudflare storage chooser to help you decide.

Create a bucket

npx wrangler r2 bucket create my-app-uploads

Add it to wrangler.jsonc:

{
  "r2_buckets": [
    {
      "binding": "UPLOADS",
      "bucket_name": "my-app-uploads"
    }
  ]
}

Now env.UPLOADS is your bucket in code.

Store a file

You store an object under a key, which is just a path-like string. The value can be text, JSON, or binary data like an uploaded file.

Here we save a file that came in from a form upload:

export default {
  async fetch(request, env) {
    const body = await request.arrayBuffer()
    await env.UPLOADS.put('avatars/user-123.png', body)
    return new Response('Saved')
  },
}

Read a file back

get returns the object. You can stream it straight into a response:

const object = await env.UPLOADS.get('avatars/user-123.png')

if (!object) {
  return new Response('Not found', { status: 404 })
}

return new Response(object.body)

object.body is a stream, so you’re not loading the whole file into memory. It just flows through to the user.

Set the content type

When you serve a file, the browser needs to know what it is. Store some metadata with the object, then use it when you serve:

await env.UPLOADS.put('avatars/user-123.png', body, {
  httpMetadata: { contentType: 'image/png' },
})

And on the way out:

const object = await env.UPLOADS.get('avatars/user-123.png')

const headers = new Headers()
object.writeHttpMetadata(headers)

return new Response(object.body, { headers })

writeHttpMetadata copies the content type (and other metadata) onto the response for you.

List and delete

List objects, optionally by prefix:

const list = await env.UPLOADS.list({ prefix: 'avatars/' })
list.objects.forEach((o) => console.log(o.key))

And delete one when it’s no longer needed:

await env.UPLOADS.delete('avatars/user-123.png')

A note on serving files

Serving files through a Worker, like above, gives you control. You can check that the user is allowed to see the file before returning it.

If a file is public and you don’t need a check, you can also connect a custom domain to the bucket and let Cloudflare serve it directly. Even faster, even less code.

When to use R2

R2 is for files: user uploads, images, video, generated documents, backups. Anything that isn’t structured rows (D1) or simple key lookups (KV).

The no-egress pricing makes it especially good for things people download a lot. The full reference is in the R2 docs.

~~~

Related posts about cloudflare: