Cloudflare R2:免费 10G 对象存储 + 自建图床完全指南
CF R2 是 Cloudflare 的对象存储服务,完全 S3 兼容,关键卖点是出站流量免费——这点直接把传统 S3 一年几百刀的图床账单干到 0。
10G 存储 + 100 万 Class A 操作 + 1000 万 Class B 操作的免费额度,对个人图床 / 博客 / 小项目来说足够用到天荒地老。这篇把开通到接入 PicGo 的完整流程串一遍。
一、为什么选 R2 做图床
跟其它对象存储对比:
| 厂商 | 免费额度 | 1TB 月费 | 出站流量 |
|---|---|---|---|
| Cloudflare R2 | 10G + 100w A + 1000w B 操作 | $15 | 免费 |
| Backblaze B2 | 10G + 每天 1G 下载 | $6 | 3 倍存储免费,超出 $0.01/GB |
| 七牛云 | 10G + 10G 流量/月 | 国内便宜 | 国内 0.27 元/GB |
| AWS S3 | 5G(12 个月) | $23 | 前 100G 0.09/GB |
| 阿里云 OSS | 5G | $18 | $0.07-0.12/GB |
💡 R2 的”出站免费”对图床场景是颠覆性的——图床本质是个超高出站流量的应用。
二、整体架构
边缘缓存] W -->|miss 时回源| R2[R2 Bucket
实际存储] PG[PicGo / PicList
本地工具] -->|S3 API| R2 R2 -.绑定.-> CD[自定义域名
img.your-domain.com]
| 组件 | 职责 |
|---|---|
| R2 Bucket | 存图片文件 |
| 自定义域名 | 让 URL 好看 + 走 CDN 缓存 |
| API Token | PicGo 上传用的凭证 |
| PicGo/PicList | 本地上传工具 |
三、开通 R2
3.1 充值(必须)
R2 虽然有免费额度,但需要绑定信用卡才能开通。
CF 控制台 → R2 → Overview → 跟着提示绑卡。绑完会让你选订阅,选免费层:
- 10G 存储
- 100 万 Class A 操作(写入相关:PUT/POST/COPY)
- 1000 万 Class B 操作(读取相关:GET/HEAD)
只要不超过这个额度,账单永远 $0。
3.2 创建 Bucket
R2 → Create bucket:
| 字段 | 推荐 |
|---|---|
| Bucket name | img-bed(全小写,连字符) |
| Location | Automatic(CF 自动选最优) |
创建完成。这时候你的 bucket 还没有公开访问入口。
四、绑定自定义域名(关键)
R2 默认的 pub-xxxxx.r2.dev 域名速度慢、不能商用。必须绑自定义域名才能正常做图床。
4.1 前提
你的域名已经托管到同一个 CF 账号下。
4.2 操作
在 bucket 详情页:
Settings → Public access → Custom Domains → Connect Domain:
| 字段 | 值 |
|---|---|
| Domain | img.your-domain.com |
CF 会自动加 CNAME 记录、签 SSL,几分钟后这个域名就指向你的 bucket 了。
4.3 验证
随便上传一张图到 bucket(控制台直接拖文件),然后访问:
https://img.your-domain.com/test.png能看到图片 = 成功。
💡 走自定义域名的请求全部走 CF CDN,比直连 R2 快好几倍。CDN 命中后甚至不计 R2 的 Class B 操作。
五、创建 API Token(给 PicGo 用)
R2 → Manage R2 API Tokens → Create API token:
| 字段 | 推荐 |
|---|---|
| Token name | picgo-upload |
| Permissions | Object Read & Write |
| Specify bucket(s) | Apply to specific buckets only:选你的 bucket |
| TTL | 不设(永久) |
创建后会显示一次Access Key ID + Secret Access Key,立刻保存(关页面就再也看不到)。
还有一个关键参数:
Endpoint:https://<accountid>.r2.cloudflarestorage.com也要记下来。
🪤 千万别把这三个值传到 GitHub / 共享出去。任何人拿到都能往你 bucket 写文件、删文件、跑爆你的额度。
六、接入 PicGo / PicList
6.1 装 PicList(推荐,PicGo 加强版)
https://github.com/Kuingsmile/PicList/releases下载对应平台的安装包。
6.2 配置 S3 上传
图床设置 → AWS S3 → 新建配置:
| 字段 | 值 |
|---|---|
| 应用密钥 ID(Access Key) | 上一步保存的 Access Key ID |
| 应用密钥(Secret Key) | 上一步保存的 Secret Access Key |
| 桶名(Bucket) | 你的 bucket 名(如 img-bed) |
| 文件路径(重要) | {year}/{month}/{md5}.{extName} |
| 自定义节点(Endpoint) | https://<accountid>.r2.cloudflarestorage.com |
| 自定义域名(Custom URL) | https://img.your-domain.com |
| 自定义区域(Region) | auto |
| 路径风格(path-style) | 关闭(即用 virtual-hosted-style) |
| ACL | 不设 / public-read |
文件路径模板说明:
| 模板 | 效果 |
|---|---|
{md5}.{extName} | 用文件 MD5 命名(推荐:相同文件不重复上传) |
{year}/{month}/{md5}.{extName} | 按年/月分目录 |
{filename}.{extName} | 用原文件名(可能冲突) |
{timestamp}.{extName} | 时间戳命名 |
6.3 设为默认 + 测试
设为默认图床后,截图工具调 Win + Shift + S → 复制到剪贴板 → PicList 自动上传 → 返回 markdown 链接。
直接试一下:
七、为什么 {md5}.{extName} 是最佳实践
最终 URL = 域名 + 路径https://img.your-domain.com / 2026/06/abc123def456.png ↑ ↑ 你完全控制 你完全控制只要这两点保持一致,后端存储可以随时切换:
R2 哪天涨价 / 你想换别的,只要文件名保持一致,旧文章里所有图片链接都不需要改——CF DNS 改个 origin 就行。
八、迁移备份策略
虽然 R2 很稳,重要数据务必有备份。推荐用 rclone:
8.1 装 rclone
curl https://rclone.org/install.sh | sudo bashrclone config按提示加两个 remote:
| Remote 名 | 类型 |
|---|---|
r2 | S3-compatible(填 R2 的 endpoint + token) |
gdrive 或 b2 | Google Drive / Backblaze B2 |
8.2 同步备份
# R2 → Backblaze B2rclone sync r2:img-bed b2:img-bed-backup
# R2 → Google Driverclone sync r2:img-bed gdrive:img-bed-backup/
# 加进 cron 每周一次0 3 * * 0 rclone sync r2:img-bed b2:img-bed-backup --log-file /var/log/rclone.log8.3 灾难恢复
如果 R2 哪天挂了:
# 反向同步回去rclone sync b2:img-bed-backup r2:img-bed或者直接把域名指向 Alist + OneDrive,博客文章一行不用改。
九、CDN 缓存优化
R2 的请求计费按 Class A/B 操作,通过 CDN 缓存能大幅减少。
CF 控制台 → Caching → Cache Rules → Create rule:
| 字段 | 值 |
|---|---|
| Rule name | r2-images-cache |
| Field | Hostname |
| Operator | equals |
| Value | img.your-domain.com |
| Eligible for cache | ✅ |
| Edge TTL | 1 month |
| Browser TTL | 7 days |
之后大部分请求被 CDN 直接命中,根本不会回源到 R2。
十、踩坑清单
| 现象 | 原因 | 解决 |
|---|---|---|
| PicList 上传失败 403 | API Token 权限不对 | 重建 Token,选 Object Read & Write |
| 上传成功但访问 404 | 自定义域名没绑 / DNS 没生效 | 确认域名绑定 + 等 5 分钟 |
pub-xxx.r2.dev 速度慢 | 默认域名没走 CDN | 必须绑自定义域名 |
| Endpoint 写错 | 用了 dashboard URL 而不是 S3 endpoint | 用 https://<accountid>.r2.cloudflarestorage.com |
| Region 报错 | R2 不用 region 但 S3 库要求 | 写 auto 或 us-east-1 |
| 同样文件上传两次出现两个 URL | 文件名用了 timestamp | 改用 {md5} |
| 突然账单从 $0 涨到几刀 | Class A 操作超 100w | 看监控 + 加 CDN 缓存 |
十一、几条实用经验
- 永远绑自定义域名——R2 的 r2.dev 域名只能调试用。
- PicList > PicGo:PicList 是社区活跃 fork,bug 少很多。
{md5}.{extName}是命名圣经:永久不冲突 + 重复上传不浪费空间。- 加 CDN 缓存规则:能让 R2 操作量降一两个数量级,免费额度永远花不完。
- rclone 周备份到另一个对象存储,重要图片不至于因为一次误操作消失。
- 图片直接拖到 R2 控制台也能上传,临时传几张文件不用开 PicList。
按这套配下来,你的图床年费从几百刀变 $0,速度还比国内大厂稳。