侧边栏壁纸
博主头像
无涯茶榻

茶烟半榻窗竹雨,一卷残书梦里秋

  • 累计撰写 43 篇文章
  • 累计创建 1 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Cloudflare R2 图床实操:从开通到接进 Halo,以及三处教程没说清的地方

结论先给:R2 依然是目前个人图床里性价比最高的选择,免费额度够用、出站不收流量费、不用担心小厂跑路。但它并不是「注册完就能传图」,中间有两道门槛,跨过去之后才叫一劳永逸。

Cloudflare R2 图床示意:图片从云端存储桶流向博客页面
图片存在桶里,读者看到的是自己域名下的链接

一、为什么是 R2

把候选方案过一遍,理由其实只有三条:

  • 额度实在:每月 10 GB 存储、100 万次写、1000 万次读,个人博客很难跑满;
  • 出站不计费:这条最容易被忽略,却是图床场景的关键——图片被反复读取,流量费才是真成本;
  • S3 协议兼容:几乎一切工具都能接,PicGo、Halo、rclone、自家脚本都行。

代价是它长得不像图床:没有中文后台,没有「复制链接」按钮,一切都得自己拼参数。所以下面这几步,顺序不能乱。

二、开通:从账号到能上传

  1. 登录 Cloudflare,进入左侧「R2 对象存储」,按提示订阅 R2(这一步要绑付款方式,信用卡或国区 PayPal 都行);
  2. 创建存储桶,名称自取,位置选离读者近的——面向中文读者就选亚太;
  3. 进入桶的「设置」,找到 r2.dev 子域,允许访问(输入 allow 确认);
  4. 回到「对象」页,拖一张图上去,点开它,复制生成的网址试试。

到这一步,外网能打开、国内大概率打不开。这不是配置错了,是 r2.dev 这个默认域名在国内的连通性本来就不稳,官方也明确不建议把它用于生产。于是进入第三关。

三、域名:绕不过去的那道坎

解法是把自有域名托管到 Cloudflare,再把它绑到桶上,让图片走 Cloudflare 的 CDN。

  1. Cloudflare 左侧「域」→ 填入域名,套餐选免费;
  2. 在激活页复制两个名称服务器(NS);
  3. 去域名注册商那里把 NS 改掉;
  4. 等状态从「待处理」变成「活动」;
  5. 回到 R2 → 桶 → 设置 → 自定义域 → 连接域。

绑好之后,同一个文件会多出一条 https://img.你的域名/路径 的链接。这条链接才是能长期用的那条。

四、密钥:给程序用的那一对

图床工具不认你的账号密码,只认 S3 密钥。在 R2 概览页点「API → 管理 API 令牌」,新建令牌时权限只给「对象读和写」,范围限定到具体那个桶。拿到三样东西:Access Key ID、Secret Access Key、以及账户的 S3 端点。

用 PicGo 的话,装 S3 插件后填这张表:

参数填什么
密钥 ID / 密钥上一步生成的那一对
存储桶你的桶名
自定义节点https://<账户ID>.r2.cloudflarestorage.com
地区auto
文件路径picgo/{全文件名}
自定义域名https://img.你的域名(要带协议头)

五、验证:别看界面,看返回值

后台显示「已连接」不算证据。我习惯用三条独立证据收尾:

  • 列得出对象:用 S3 客户端列一次桶,返回 200 且条数对得上;
  • 写得进去:上传一个小文件,再删掉;
  • 公网打得开:拿图片链接直接请求,状态 200、类型正确、字节数和后台一致。

顺手看一眼响应头里的 cf-cache-status:出现 HIT,说明图片已经在 Cloudflare 边缘缓存里,读者访问不会每次回源。

六、如果你也用 Halo,有更短的路

PicGo 适合「站外单张图、批量传、要 Markdown 链接」的场景。如果你是 Halo 用户,其实可以跳过它:

  1. 装官方插件「对象存储(Amazon S3 协议)」;
  2. 在「附件 → 存储策略」新建一个 S3 策略,把上面那套参数填进去;
  3. 把它设为默认。

之后在编辑器里插图,文件会直接落到 R2,链接就是你的自定义域。注意插件版本:新版对 Halo 版本有要求,装之前先对一下,不要盲目上最新。

另外要清楚:切换存储策略只影响新上传。历史附件还在服务器本地,要迁移得单独做。

七、成本、缓存与防盗链:跑通之后的样子

免费额度之外的单价很低(存储约每 GB 每月一角钱量级,以官网为准)。真正决定体验的是缓存和防盗链这两件事,下面是我实际跑通的配置和回测数字。

1. 防盗链:一个开关,或者一条规则

最省事的是打开 Scrape Shield 里的热链接保护:

Cloudflare → 你的域名 → 安全性 → 设置 → 客户端滥用 → 热链接保护 → 开

它的行为是:Referer 为空放行;Referer 非空且不是本站 → 403。想要更精细(放行搜索引擎、放行指定 UA),就改用 WAF 自定义规则,表达式写:

(http.host eq "img.wycha.top" and http.referer ne "" and not http.referer contains "wycha.top")

动作选 Block。两条路效果一样,前者一键、后者可加白名单。

2. 缓存:一条 Cache Rule 只管图片域名

在 缓存 → Cache Rules 里建一条:

  • 表达式:http.host eq "img.wycha.top"
  • 边缘 TTL:30 天,模式选覆盖源站
  • 浏览器 TTL:1 天,同样覆盖源站

用 API 建出来长这样,关键是 action_parameters:

{
  "action": "set_cache_settings",
  "expression": "(http.host eq \"img.wycha.top\")",
  "action_parameters": {
    "cache": true,
    "edge_ttl": { "mode": "override_origin", "default": 2592000 },
    "browser_ttl": { "mode": "override_origin", "default": 86400 }
  }
}

把规则限定在图片 host 上是有意的:HTML 页面不能被这条规则波及,否则文章更新后读者看到的是旧页面。

3. 回测:四条证据

配置完之后我跑了四组请求,结果如下:

请求结果
图片(已缓存)200,max-age=86400,cf-cache-status: HIT,age: 2009
图片(新缓存键)200,max-age=86400,首次 MISS,之后命中
文章页 HTML200,no-cache, no-store,未被规则波及
图片 + 外站 Referer403,被边缘拦下

有两个细节要注意:

  • 必须放行空 Referer。微信编辑器抓图、Telegram/Slack 预览、RSS 阅读器、读者直接把链接粘到地址栏,全是空 Referer;规则写成 referer ne "" 就是在保护这条。
  • 边缘 TTL 不会出现在响应头里。能看到的只有 max-age 和 cf-cache-status,想确认 30 天边缘缓存,得看 Cache 分析或 Rules 的命中统计。

一句提醒:大文件不要放在自建图床上。视频动辄几百兆,既拖慢首屏,也容易让边缘缓存失效、把回源打成常态。视频走 B 站之类的平台外链,图片才是这套方案的主场。

结语

整套方案的真正价值不在「免费」,而在所有权:域名是你的、桶是你的、链接格式由你定,换工具不用换链接。做完之后你会得到一条稳定的图片域名,和一套随时能复制到下一个项目的参数。

如果只记一句话:先把域名托管好,再谈图床。顺序反了,后面每一步都要返工。

0

评论区