Cloudflare R2
零 egress 費用的物件儲存服務,S3 相容 API 與實務操作指南
Overview##
Cloudflare R2 是 Cloudflare 的物件儲存服務。它的 API 與 Amazon S3 完全相容,最大的賣點是 零 egress 費用。
R2 vs S3###
| 面向 | S3 | R2 |
|---|---|---|
| Egress 費用 | $0.09/GB | 免費 |
| 儲存費用 | $0.023/GB/月 | $0.015/GB/月 |
| API 相容性 | — | S3 API 完全相容 |
| 全球分佈 | 需設定 Region | 自動分佈 |
| 免費額度 | 有限 | 10GB 儲存 + 1000 萬次讀取/月 |
Tip
如果你的應用有大量讀取流量(圖片、影片、靜態資源),光是 egress 費用的差異就能省下可觀的成本。以每月 1TB 流出量計算:S3 約 0。
核心概念###
R2 的資料模型跟 S3 一樣:
Account
└── Bucket(容器)
└── Object(物件)
├── Key(路徑,如 images/photo.jpg)
├── Value(檔案內容)
└── Metadata(自訂 headers)
| 概念 | 說明 |
|---|---|
| Bucket | 物件的容器,名稱全域唯一 |
| Object | 單一檔案,最大 5TB |
| Key | 物件的路徑(支援 / 模擬目錄結構) |
| Multipart Upload | 大檔案分塊上傳 |
Setup##
建立 Bucket###
透過 Cloudflare Dashboard 或 Wrangler CLI:
# 安裝 Wrangler
pnpm add -g wrangler
# 登入
wrangler login
# 建立 Bucket
wrangler r2 bucket create my-assets
# 列出所有 Bucket
wrangler r2 bucket list
API Token###
使用 S3 API 需要建立 R2 API Token:
- Cloudflare Dashboard → R2 → Manage R2 API Tokens
- Create API Token
- 取得
Access Key ID和Secret Access Key - Endpoint:
https://<ACCOUNT_ID>.r2.cloudflarestorage.com
Usage##
AWS SDK(S3 相容)###
因為 API 相容,可以直接使用 AWS SDK:
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';
const client = new S3Client({
region: 'auto',
endpoint: 'https://<ACCOUNT_ID>.r2.cloudflarestorage.com',
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
},
});
// 上傳
await client.send(
new PutObjectCommand({
Bucket: 'my-assets',
Key: 'images/photo.jpg',
Body: fileBuffer,
ContentType: 'image/jpeg',
}),
);
// 下載
const response = await client.send(
new GetObjectCommand({
Bucket: 'my-assets',
Key: 'images/photo.jpg',
}),
);
Wrangler CLI###
# 上傳檔案
wrangler r2 object put my-assets/images/photo.jpg --file ./photo.jpg
# 下載檔案
wrangler r2 object get my-assets/images/photo.jpg --file ./downloaded.jpg
# 刪除檔案
wrangler r2 object delete my-assets/images/photo.jpg
# 列出物件
wrangler r2 object list my-assets --prefix images/
Workers 整合###
在 Cloudflare Workers 中直接存取 R2,不需要 API Token:
// wrangler.toml
// [[r2_buckets]]
// binding = "ASSETS"
// bucket_name = "my-assets"
export default {
async fetch(request: Request, env: { ASSETS: R2Bucket }) {
const url = new URL(request.url);
const key = url.pathname.slice(1); // 移除開頭的 /
if (request.method === 'GET') {
const object = await env.ASSETS.get(key);
if (!object) return new Response('Not Found', { status: 404 });
return new Response(object.body, {
headers: { 'Content-Type': object.httpMetadata?.contentType ?? '' },
});
}
if (request.method === 'PUT') {
await env.ASSETS.put(key, request.body);
return new Response('OK');
}
return new Response('Method Not Allowed', { status: 405 });
},
};
Note
Workers 透過 binding 直接存取 R2,走的是 Cloudflare 內部網路,不計入 API 請求次數,效能也更好。
Public Access##
R2 Bucket 預設是私有的。兩種方式開放公開存取:
方法一:Custom Domain###
把你的域名綁定到 Bucket,透過 Cloudflare CDN 提供服務:
- R2 → Bucket → Settings → Public Access
- Connect a Custom Domain →
assets.example.com - Cloudflare 自動建立 DNS 紀錄
用戶請求 assets.example.com/images/photo.jpg
→ Cloudflare CDN(快取)
→ R2 Bucket
方法二:r2.dev 子域名###
快速開啟公開存取,不需要自訂域名:
https://pub-<hash>.r2.dev/images/photo.jpg
Warning
r2.dev 子域名有速率限制,不適合生產環境。正式使用請綁定 Custom Domain。
Best Practices##
| 實踐 | 說明 |
|---|---|
| Key 命名 | 用 / 模擬目錄結構:uploads/2026/04/photo.jpg |
| Content-Type | 上傳時務必設定,否則下載時會是 application/octet-stream |
| 大檔案 | 超過 100MB 使用 Multipart Upload |
| 存取控制 | 生產環境用 Custom Domain + Workers 做權限控制 |
| 備份 | R2 跨區域自動複製,但重要資料建議額外備份 |
Quiz##
Summary##
- R2 是 S3 相容的物件儲存,殺手級功能是零 egress 費用
- 可以直接用 AWS SDK 操作,只需替換 endpoint
- Workers binding 是最佳存取方式——無需 Token、走內部網路
- 公開存取推薦用 Custom Domain,
r2.dev有速率限制不適合生產 - 上傳時務必設定 Content-Type,大檔案使用 Multipart Upload
留言 (0)
登入後即可留言