Cloudflare R2
把 Cloudflare R2 配成 01MVP 图片资产仓库
Cloudflare R2 适合做 01MVP 的公共图片资产仓库:它兼容 S3 API,模板现有的 @01mvp/storage 不需要额外适配;公开访问用自定义域名,写文档时可以直接插入稳定的图片 URL。
推荐第一阶段这样落地:
Cloudflare R2
+ assets.01mvp.com
+ VS Code 粘贴上传
+ R2 Web 管理后台
+ 上传前本地压缩这里暂不接入 Cloudflare Image Transformations。图片压缩先放在上传前处理,后续确实需要响应式尺寸、格式自动转换或站点性能优化时再单独开启。
推荐结构
Bucket
01mvp-public-assets用于公开图片、文章截图、封面图和公开下载文件。以后如果要放会员资料、未发布素材或课程源文件,再单独创建 01mvp-private-assets,不要把私有内容放进公开 bucket。
自定义域名
https://assets.01mvp.com正式文章和文档里只使用这个域名,不长期使用 r2.dev。r2.dev 适合测试;生产访问使用自定义域名,后续才能配合 Cloudflare Cache、WAF、访问控制等能力。
目录约定
images/01mvp/2026/05/demo.png
images/articles/codex-game-dev/cover.png
images/screenshots/2026/05/dashboard.png
files/downloads/01mvp-template.zip文章中最终插入:
使用条件
- Cloudflare 账号已经能启用 R2。R2 有免费额度,但它是用量计费产品,正式使用前需要确认账号 Billing/付款方式状态。
01mvp.com在可配置的 Cloudflare zone 中。R2 自定义域名需要把域名添加到同一个 Cloudflare 账号,或者按 Cloudflare 的 partial/CNAME setup 接入。- R2 API Token 只给目标 bucket 的读写权限,不使用全账号管理员 Token。
- 公开 bucket 只放可公开访问的文件。私有资料以后放独立 bucket,并通过后端或签名 URL 访问。
- 面向中国大陆稳定分发、OTA、App 安装包下载时,不要只依赖 R2;把国内回源作为扩展方案单独设计。
创建 R2 bucket
在 Cloudflare Dashboard > R2 Object Storage 创建:
01mvp-public-assets存储类型先选 Standard。第一阶段图片、截图、文档附件都放这里。
绑定自定义域名
进入 bucket 的 Settings > Custom Domains,添加:
assets.01mvp.com等待状态变为 Active 后,上传一个测试文件并访问:
https://assets.01mvp.com/images/01mvp/test.png不要把生产文章图片指向 pub-xxxxx.r2.dev。
创建 R2 API Token
进入 R2 > Manage R2 API Tokens,创建 S3-compatible credentials。权限建议只覆盖 01mvp-public-assets,用于上传、删除和读取对象。
不要把已有的高权限 CLOUDFLARE_API_TOKEN 直接给 VS Code 插件或 R2 Web 使用。R2 S3 凭证应单独创建 bucket 级 Object Read & Write token。Cloudflare API token 如果没有创建 User API Token 的权限,就只能在 Dashboard 里手动创建这组 S3 credentials。
最小权限 R2 API Token
这组凭证只用于 R2 Web、VS Code 图片上传插件和项目上传接口。权限只给 01mvp-public-assets 的对象读写,不给全账号权限。
- 进入 Cloudflare Dashboard
- R2 -> Manage R2 API Tokens -> Create API token
- 权限选择 Object Read & Write
- 限定范围只选
01mvp-public-assets这个桶(不要选全部桶) - 把生成的 Access Key ID / Secret Access Key 填到 R2 Web、VS Code 插件和项目环境变量
填写项目环境变量
R2 的原生 S3 API endpoint 和给读者访问的公开域名是两件事:
| 变量 | 示例 | 用途 |
|---|---|---|
S3_ENDPOINT | https://<ACCOUNT_ID>.r2.cloudflarestorage.com | 服务端连接 R2 S3 API,执行上传、删除和签名 URL 生成 |
NEXT_PUBLIC_S3_ENDPOINT | https://assets.01mvp.com | 前端和文档用来拼接公开图片、附件和下载链接 |
S3_ENDPOINT 不需要写成 NEXT_PUBLIC_。真正必须保密的是 S3_ACCESS_KEY_ID 和 S3_SECRET_ACCESS_KEY;它们只能放在服务端环境变量、受保护的管理工具或本机上传插件里。
S3_ENDPOINT=https://<ACCOUNT_ID>.r2.cloudflarestorage.com
S3_REGION=auto
S3_ACCESS_KEY_ID=你的R2AccessKeyId
S3_SECRET_ACCESS_KEY=你的R2SecretAccessKey
S3_BUCKET=01mvp-public-assets
NEXT_PUBLIC_S3_ENDPOINT=https://assets.01mvp.com配置 CORS
如果要使用浏览器直传、R2 Web 或管理页上传,需要给 bucket 配 CORS。使用 Wrangler 4 设置时,JSON 文件必须包含 rules 数组:
{
"rules": [
{
"allowed": {
"origins": [
"http://localhost:7001",
"https://01mvp.com",
"https://www.01mvp.com",
"https://r2.01mvp.com"
],
"methods": ["GET", "POST", "PUT", "DELETE", "HEAD"],
"headers": [
"authorization",
"content-type",
"x-amz-content-sha256",
"x-amz-date",
"x-amz-copy-source",
"x-amz-metadata-directive"
]
},
"exposeHeaders": ["ETag"],
"maxAgeSeconds": 86400
}
]
}然后执行:
wrangler r2 bucket cors set 01mvp-public-assets --file r2-cors.json --force如果临时使用 R2 Web 官方在线站点,也要把它的域名加入 AllowedOrigins;私有部署后只保留自己的 r2.01mvp.com。
验证上传和访问
上传一个测试文件到:
images/01mvp/test.png确认公开访问正常:
curl -I https://assets.01mvp.com/images/01mvp/test.png命令行落地参考
如果本地已经配置 CLOUDFLARE_ACCOUNT_ID 和 CLOUDFLARE_API_TOKEN,可以用 Wrangler 完成大部分配置:
wrangler whoami
wrangler r2 bucket create 01mvp-public-assets
wrangler r2 bucket domain add 01mvp-public-assets \
--domain assets.01mvp.com \
--zone-id <ZONE_ID> \
--min-tls 1.2 \
--force
wrangler r2 bucket cors set 01mvp-public-assets --file r2-cors.json --force验证公开访问:
wrangler r2 object put 01mvp-public-assets/images/01mvp/test.png \
--file ./test.png \
--content-type image/png \
--cache-control "public, max-age=31536000, immutable" \
--remote \
--force
curl -I https://assets.01mvp.com/images/01mvp/test.png返回 HTTP/2 200 就说明 R2 bucket、自定义域名和公开访问链路都正常。
自动创建 R2 S3 凭证
如果要用脚本自动创建 S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY,当前 CLOUDFLARE_API_TOKEN 需要用户级 API Token 管理权限。Cloudflare Dashboard 里的路径是:
My Profile
→ API Tokens
→ 编辑当前 token
→ User
→ API Tokens
→ Edit创建出来的 R2 S3 凭证规则:
S3_ACCESS_KEY_ID使用新建 API token 的idS3_SECRET_ACCESS_KEY使用新建 API token 的value做 SHA-256 后的 64 位 hex 字符串- token policy 只给
01mvp-public-assetsbucket 的Workers R2 Storage Bucket Item Read和Workers R2 Storage Bucket Item Write
写入本地环境变量后应得到:
S3_ENDPOINT=https://<ACCOUNT_ID>.r2.cloudflarestorage.com
S3_REGION=auto
S3_BUCKET=01mvp-public-assets
NEXT_PUBLIC_S3_ENDPOINT=https://assets.01mvp.com验证方式是用这组 S3 credentials 真实写入一个测试对象,再访问公开 URL:
curl -I https://assets.01mvp.com/images/01mvp/s3-credential-test.txt返回 HTTP/2 200 表示 S3 credentials、bucket 权限和公开域名都已经正常。
VS Code 粘贴上传
VS Code 插件只负责把本地图片上传到 R2,并把公开 URL 插入 Markdown/MDX。完整使用教程见 Paste and Upload。插件字段名会有差异,但核心配置保持一致:
endpoint: https://<ACCOUNT_ID>.r2.cloudflarestorage.com
region: auto
bucket: 01mvp-public-assets
accessKeyId: R2 Access Key ID
secretAccessKey: R2 Secret Access Key
publicUrlBase: https://assets.01mvp.com
pathTemplate: images/01mvp/{YYYY}/{MM}/{uuid}.{ext}如果使用 Paste and Upload,可以按下面填写:
| 插件字段 | 推荐填写 |
|---|---|
S3: Endpoint | https://<ACCOUNT_ID>.r2.cloudflarestorage.com |
S3: Region | auto |
S3: Bucket | 01mvp-public-assets |
S3: Access Key ID | R2 S3 credentials 的 Access Key ID |
S3: Secret Access Key | R2 S3 credentials 的 Secret Access Key |
S3: Prefix | images/01mvp/2026/05/ |
S3: Public Url Base | https://assets.01mvp.com/images/01mvp/2026/05/ |
Undo Limit | 10 |
S3: Prefix 和 S3: Public Url Base 要保持同一段路径。比如 Prefix 写 images/01mvp/2026/05/,Public Url Base 也要包含 /images/01mvp/2026/05/,否则上传位置和文章里的图片地址会对不上。
Workspace: Path 和 Workspace: Link Base 是本地保存模式使用的字段;使用 R2/S3 上传时不用填,除非你明确想把图片同时保存到仓库里。
推荐上传路径:
images/01mvp/2026/05/<hash>.png这样文章迁移、缓存规则和批量管理都更清楚。
R2 Web 管理后台
日常管理推荐用 vikiboss/r2-web。它是纯前端 R2 文件管理器,支持中文、拖拽上传、粘贴上传、图片本地压缩、文件预览、复制直链、复制 Markdown/HTML 链接。
推荐部署为:
https://r2.01mvp.com落地方式:
- 部署
vikiboss/r2-web的src目录到 Cloudflare Pages、Vercel 或 Netlify。 - 将
r2.01mvp.com绑定到这个静态站。 - 在 R2 CORS 中允许
https://r2.01mvp.com。 - 用 Cloudflare Access 限制只有自己的邮箱能打开后台。
- 在 R2 Web 中填写
01mvp-public-assets的最小权限凭证。
Cloudflare Pages 的命令行部署示例:
git clone https://github.com/vikiboss/r2-web.git
cd r2-web
wrangler pages project create 01mvp-r2-web --production-branch main
wrangler pages deploy src \
--project-name=01mvp-r2-web \
--branch=main \
--commit-message "Deploy R2 Web"部署后把 r2.01mvp.com 作为 Pages custom domain。未登录访问时,如果 curl -I https://r2.01mvp.com/ 返回 302 到 *.cloudflareaccess.com,说明 Cloudflare Access 已经保护住后台。
R2 Web 的凭证保存在浏览器本地。不要把配置分享链接或二维码发到公共渠道;API Token 也不要给全账号权限。
国内访问扩展
assets.01mvp.com 适合 01MVP 文档、博客、教程和海外读者图片。它不应该被写成中国大陆稳定分发的唯一方案。
如果要做 OTA、App 安装包、课程大文件或中国大陆用户高稳定访问,建议增加一条独立链路:
assets-cn.01mvp.com
→ 阿里云 OSS / 腾讯云 COS
→ 国内 CDN文档图片先走 R2;下载分发和大文件按访问区域拆分,后面再做同步脚本或发布流程。
图片压缩策略
第一阶段不接入 Cloudflare Image Transformations。
优先使用:
- 截图前控制尺寸
- VS Code 插件上传前压缩
- R2 Web 的本地图片压缩
- 必要时用
sharp在服务端上传前处理
后续如果需要按设备尺寸输出 WebP/AVIF,再单独设计图片优化层。