使用 Cloudflare R2 搭建免费个人图床
1. 背景
大善人 Cloudflare 为所有用户提供了 10GB 的免费 R2 对象储存服务,这对于静态个人博客等小型网站来说是极大的利好
优点:
- 不再需要服务器操心自建图床
- 不再需要考虑复杂的网络攻击防护或者 HTTPS 证书配置
- 只需要使用 CF 免费的 R2 对象储存配合 PicList,就可以快速搭建起简单可用的个人图床
- 图床访问使用 Cloudflare CDN,自带全球加速
下面详细介绍一下逐步搭建流程
2. 搭建流程
2.1. 创建 R2 储存桶
首先激活账号中的 Cloudflare R2 对象储存,图中已经给出了免费额度,这对于个人用户的小网站来说绰绰有余

创建储存桶,设置桶名字,地区选亚太地区以确保访问速度

创建完桶后,回到主界面点击 “Manage”,进入 Cloudflare R2 API Key 管理页面,创建一个 API Key,权限设置为 管理员读和写


- 记下生成的 API Key 的 S3 访问密钥 ID(AccessKeyID)和机密访问密钥(SecretAccessKey)

也不要忘了记下外面的 R2 对象储存的 S3 API 地址

- 回到储存桶管理页面,随便上传一张测试图片
test.png,以供后面测试使用

2.2. 配置防盗刷 + 防盗链
R2 对象储存的个人免费额度是有限的,为了防止 DDoS / CC 等恶意消耗流量的攻击,有必要使用 Cloudflare Workers 反代 R2 对象储存,而不是直接将 R2 储存地址对外公开。
Cloudflare Workers 同样是每天免费 10W 请求额度,对于个人网站来说完全足够。下面是部署方法:
你应该有一个域名托管在 Cloudflare。在此域名的 DNS 页面添加一个子域用于访问图床,例如 image.example.com
在 Cloudflare 主菜单找到 “Workers 和 Pages”,进入
右上角点击 “创建应用程序”,创建一个新的 Cloudflare Worker,将如下脚本上传为
worker.js,并部署export default { async fetch(request, env) { // 从环境变量读取防盗链配置 const ALLOWED_DOMAINS = (env.ALLOWED_DOMAINS_STR || "") .split(',') .map(domain => domain.trim()) .filter(domain => domain); // 1. 验证请求来源 // 当 ALLOWED_DOMAINS 不为空时,执行防盗链检查 if (ALLOWED_DOMAINS.length > 0) { const origin = request.headers.get("Origin") || ""; const referer = request.headers.get("Referer") || ""; const isAllowed = ALLOWED_DOMAINS.some(domain => origin.startsWith(domain) || referer.startsWith(domain) ); if (!isAllowed) { return new Response("Forbidden: 防盗链已启用", { status: 403, headers: { "Access-Control-Allow-Origin": "*" } }); } } // 2. 只允许 GET / HEAD if (!["GET", "HEAD"].includes(request.method)) { return new Response("Method Not Allowed", { status: 405 }); } // 3. 解析请求对象路径 const url = new URL(request.url); const objectKey = decodeURIComponent(url.pathname.slice(1)); if (!objectKey || objectKey.length > 1024) { return new Response("Bad Request", { status: 400 }); } // 4. 从 R2 读取文件 const object = await env.R2_BUCKET.get(objectKey); if (!object) { return new Response("Not Found", { status: 404 }); } // 5. 构造响应头 const headers = new Headers(); object.writeHttpMetadata(headers); headers.set("etag", object.httpEtag); headers.set("Cache-Control", "public, max-age=31536000, immutable"); headers.set("Access-Control-Allow-Origin", origin || ALLOWED_DOMAINS[0]); // 6. 处理条件请求(If-None-Match) const ifNoneMatch = request.headers.get("If-None-Match"); if (ifNoneMatch && ifNoneMatch === object.httpEtag) { return new Response(null, { status: 304, headers }); } // 7. 返回文件流 return new Response(object.body, { headers }); } };(脚本参考自 Linux.DO 论坛 @leonkuku 大佬)
注意这里用到了两个环境变量:
R2_BUCKET用于关联所使用的 Cloudflare R2 储存桶ALLOWED_DOMAINS_STR用于防盗链,可选是否启用。启用防盗链之后,只有发自指定域名的请求才能成功访问图床
在 Worker 的绑定页面,为
R2_BUCKET变量绑定使用的 R2 储存桶

在 Worker 的设置页面
- 添加自定义域,设置为你刚刚选取的访问图床使用的域名。例如:
image.example.com - 如果需要使用防盗链,则继续添加环境变量,为
ALLOWED_DOMAINS_STR变量配置允许访问图床的域名列表,域名之间用逗号隔开。例如:https://blog.example.com,https://image.example.com
- 添加自定义域,设置为你刚刚选取的访问图床使用的域名。例如:
回到 Worker 的部署页面点击 “部署”,部署最新版本的
worker.js测试效果:用浏览器访问 https://image.example.com/test.png (改成你自己的图床域名),只要能看到图片,就代表配置成功
如果开启了防盗链,需要用终端执行如下命令进行测试:(链接都需要改成你自己的图床域名)
curl -I -H "Referer: https://image.example.com" "https://image.example.com/test.png"
2.3. 配置 PicList 图片上传
下面,开始配置 Piclist 图床客户端,以方便地向 Cloudflare R2 储存上传图片
- 安装 PicList 客户端(项目地址:https://github.com/Kuingsmile/PicList )
- 配置图床:切换到图床设置页面,选择 AWS S3,各配置项按实际情况填写:
- 配置名:自己起一个名字
- AccessKeyId:填之前记录的 S3 访问密钥 ID(AccessKeyID)
- SecretAccessKey:填之前记录的 机密访问密钥(SecretAccessKey)
- Bucket:填你创建储存桶时设置的储存桶名字
- 上传路径:按你的需要进行设置,没有特殊需求的话保持默认即可
- Region:填
auto - 自定义节点:填之前记录的 S3 API 地址
- 自定义域名:填你之前设置的访问图床的域名,例如 https://image.example.com
- 其他设置保持默认即可
- 保存图床设置,将本配置设置为默认图床
- 回到图片上传页面,有需要的话可以设置一下右上角的图片处理设置

- 在上传页面上传一张图片。上传完毕后,PicList 会自动将图片的外链 URL 复制到你的剪贴板
- 大功告成!
2.4. 为图床配置缓存(可选)
Cloudflare R2 每月有 1000W 免费读取次数。如果你不放心,可以再增加一层缓存,既可以减少回源读取次数,又能加速访问速度。不过缓存可能导致图片修改以后更新不及时,有这方面需求的可以不启用此功能。
具体方法:
- 在 Cloudflare 的域名管理页面菜单中找到 “缓存”,进入 Cache Rule,点击创建规则
- 如下设置缓存配置
- 将 URL 匹配的值改成你自己的图床域名,比如
https://image.example.com/* - 将启用边缘 TTL 设置,选择指定 TTL,时间选择 1 天。这个时间是 Cloudflare 缓存图片的时间,可按你的需求自行调整
- 将 URL 匹配的值改成你自己的图床域名,比如

- 配置完成后点击右下角部署,稍等一会后缓存就将生效
- 启用缓存后,每当图床的某张图片被访问,Cloudflare 会把它放入全球 CDN 缓存 24 小时,24 小时以内对这张图片的任意访问都将直接从缓存读取。这样大大降低了 Workers 和 R2 储存的读取请求开销,也提高了响应速度
3. 图床使用
配置完成后,图床使用方法如下:
- 打开 PicList,点击 “上传” 按钮选择要上传的图片文件,或者点击 “剪贴板图片” 按钮上传剪贴板中的图片
- 稍等片刻
- 上传完毕,PicList 自动将图片外链复制到剪贴板
随处使用你的外链吧~
4. More…
如果以后随着网站规模增长,R2 对象储存的免费额度不够使用了,可以继续使用收费额度(R2 收费并不贵),或者迁移到其他 S3 兼容的对象储存平台,乃至在自己的服务器上自建 S3,不管怎么样都是相当方便的。