在写博客或者做个人项目时,一个稳定且免费的图床必不可少。目前市面上的图床要么限制多,要么面临随时跑路的风险。今天记录一下如何使用 Cloudflare R2 + Pages 搭建一个属于自己的免费图床。
这个方案有几个巨大的优势:
- 免流量的费用:Cloudflare R2 的读取操作和流量完全免费。
- 国内访问友好:使用 Pages 提供的
pages.dev域名,相比被墙的workers.dev来说,在国内很多时候可以直连,速度尚可。 - 防超额扣费:通过 Pages Functions 代理和强缓存,配合 Fail closed 机制,杜绝了超额扣费的风险。
- 目录结构自定义:直接映射 R2 中的文件夹结构,无需重新部署即可上传新图。
准备工作
- 一个 Cloudflare 账号。
- 一张银行卡(储蓄卡或信用卡都可以)或 PayPal(开通 R2 需要验证,但不会产生费用)。
第一步:创建并配置 R2 存储桶
- 登录 Cloudflare 控制台,在左侧导航栏找到并进入 R2。
- 点击 创建存储桶,并给你的图床起个名字,例如
images,位置选择 自动(亚太地区),默认存储类选择 标准。 - 创建完成后,进入该存储桶的 设置 页面。
- 默认情况下,存储桶不能公开访问,但还是建议确认一下。 找到 公共开发 URL,确认其为关闭的。我们要保证存储桶是私有的,所有访问必须走我们自己的 Pages。
- 在存储桶中点击 创建文件夹 ,然后进去上传图片。比如创建一个
example文件夹,里面再建一个album文件夹,上传一张01.jpg,它的 Key 就是example/album/01.jpg。
第二步:创建 Pages 项目并绑定 R2
- 在控制台进入 Workers 和 Pages,创建一个新的 Pages 项目(Pages 项目在底下的小字部分),选择 拖放文件 选项。
- 进入 Pages 项目的 设置 -> 绑定。
- 点击 添加 -> R2 存储桶:
- 变量名称 填入
Images(代码里会用到,请保持一致,注意大小写)。 - R2 存储桶 选择你刚创建的
images。
- 变量名称 填入
- 保存后,必须重新部署一次项目,绑定才会生效。
第三步:编写 Functions 代码
我们要让 Pages 在根目录下拦截所有请求,去 R2 里找对应的图片。
由于在 Cloudflare Pages 中,要使 functions 生效,必须要使用 Wrangler 部署。因此,我们在电脑的空白文件夹下创建 functions/[[path]].js 文件,并写入以下代码:
export async function onRequest(context) { const { request, env, params } = context;
if (request.method !== "GET" && request.method !== "HEAD") { return new Response("Method Not Allowed", { status: 405 }); }
// params.path 是路径片段数组,例如 /example/01.jpg → ["example", "01.jpg"] const rawKey = (params.path || []).join("/");
// 安全清理,防止 ../ 路径遍历 const key = rawKey .split("/") .filter((segment) => segment && segment !== "." && segment !== "..") .join("/");
// 根路径 / 没有对应对象,返回一个简单提示 if (!key) { return new Response("Image Hosting", { status: 200 }); }
// 这里的 Images 应该和上面 R2 存储桶的变量名称一致 const object = await env.Images.get(key); if (object === null) { return new Response("Not Found", { status: 404 }); }
const headers = new Headers(); object.writeHttpMetadata(headers); headers.set("etag", object.httpEtag); headers.set("Cache-Control", "public, max-age=31536000, immutable");
if (request.method === "HEAD") { return new Response(null, { headers }); }
return new Response(object.body, { headers });}第四步:使用 Wrangler 部署项目
- 确保你的电脑安装了
Node.js。 - 打开终端(命令行),进入你刚刚创建
functions文件夹的根目录。 - 运行以下命令进行部署(第一次运行可能会提示你登录 Cloudflare 账号,按提示授权即可):
npx wrangler pages deploy . --project-name=<你的项目名称>部署成功后,终端会返回一个预览或生产环境的 URL。
第五步:设置防超额扣费
这是整个方案中最核心的一步。由于 R2 免费额度用完后是 自动按量计费 的,为了确保万无一失,我们需要利用 Pages Functions 的额度限制来间接锁死 R2 的消耗。
-
进入你的 Pages 项目,点击 设置 -> 运行时。
-
找到 失败开放 (Fail open) / 失败关闭 (Fail closed) 选项,将其修改为 失败关闭 (Fail closed),然后保存。
第六步:测试与验证
部署完成后,在浏览器中打开你的图片链接:
https://你的项目名称.pages.dev/example/album/01.jpg如果图片正常显示,说明基本配置已经成功。至此,你的专属免费图床已经搭建完毕。
(可选)设置自定义域名
如果你希望图床链接使用自己的域名,可以在这一步继续配置,整个配置过程完全 不影响你已有的主域名或其他子域名解析。
- 在 Cloudflare Pages 中添加域名
-
在 Cloudflare 中选择你的图床项目,点击 自定义域 -> 设置自定义域,输入你想要的子域名(如
imgs.你的域名.com)并继续。 -
页面会给出一个 CNAME 目标地址(通常是你的
项目名.pages.dev),请记录下来。
- 在域名服务商处配置解析
-
登录你的域名后台,进入 Advanced DNS 选项。
-
添加一条新的 CNAME Record 并保存:
| Host | Value | TTL |
|---|---|---|
imgs(你的子域名前缀) | 刚才记录下的 CNAME 目标地址 | 自动 (Automatic) |
- 等待生效 DNS 通常需要几分钟到半小时生效。回到 Cloudflare Pages 的页面,当状态变为 “活动” (Active) 时,说明配置成功,SSL 证书也会自动签发。
配置完成后,你原有的 pages.dev 地址依然可以访问。但在博客中引用图片时,你可以使用你自己的专属链接了,例如将 https://你的项目名称.pages.dev/example/album/01.jpg 替换为 https://imgs.你的域名.com/example/album/01.jpg。
日常使用指南
-
上传新图:直接在 Cloudflare R2 控制台进入对应的文件夹上传即可,无需再次运行 Wrangler 部署,URL 会自动生效。
-
引用图片:在博客或论坛中,直接使用
https://你的项目名称.pages.dev/文件夹/子文件夹/文件名.jpg即可。 -
代码备份:请务必妥善保存本地的
functions/[[path]].js文件。由于我们使用的是直接上传部署,云端的代码只是编译后的产物,本地代码可以帮助你日后修改配置。
分享文章
生成精美分享图或复制链接,与更多人分享本文。
继续阅读
最后更新于 ,距今已过 3 天
部分内容可能已过时