The Own Lab The Own Lab

Cloudflare R2

零 egress 費用的物件儲存服務,S3 相容 API 與實務操作指南

Overview##

Cloudflare R2 是 Cloudflare 的物件儲存服務。它的 API 與 Amazon S3 完全相容,最大的賣點是 零 egress 費用

R2 vs S3###

面向S3R2
Egress 費用$0.09/GB免費
儲存費用$0.023/GB/月$0.015/GB/月
API 相容性S3 API 完全相容
全球分佈需設定 Region自動分佈
免費額度有限10GB 儲存 + 1000 萬次讀取/月

Tip

如果你的應用有大量讀取流量(圖片、影片、靜態資源),光是 egress 費用的差異就能省下可觀的成本。以每月 1TB 流出量計算:S3 約 90R290,R2 為 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:

  1. Cloudflare Dashboard → R2 → Manage R2 API Tokens
  2. Create API Token
  3. 取得 Access Key IDSecret Access Key
  4. 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 提供服務:

  1. R2 → Bucket → Settings → Public Access
  2. Connect a Custom Domain → assets.example.com
  3. 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##

Single Choice

R2 相比 S3 最大的成本優勢是什麼?

Single Choice

為什麼可以用 AWS SDK 來操作 R2?

Single Choice

Workers 透過 binding 存取 R2 有什麼優勢?

Single Choice

以下哪個不是 R2 Bucket 公開存取的方式?

Summary##

  • R2 是 S3 相容的物件儲存,殺手級功能是零 egress 費用
  • 可以直接用 AWS SDK 操作,只需替換 endpoint
  • Workers binding 是最佳存取方式——無需 Token、走內部網路
  • 公開存取推薦用 Custom Domain,r2.dev 有速率限制不適合生產
  • 上傳時務必設定 Content-Type,大檔案使用 Multipart Upload

留言 (0)

登入後即可留言