存储

Cloudflare R2 的创建、绑定与文件 API

最近更新 2026 年 10 月 21 日


文件存 Cloudflare R2,经 Workers 的 BUCKET binding 访问,零 egress 费用。代码在 src/storage/。

存储模块已实现但未接线:features.enableFileUpload 默认 false,仓库内没有路由 使用它。本页讲的是「要用时怎么接」——未开通 R2 不影响模板正常运行。

前提条件

Token 需含 Account → Workers R2 Storage → Edit,见 Cloudflare。

设置

1. 在 Dashboard 开通 R2

这一步无法跳过,也无法经 API 完成。 首次使用必须先在 Dashboard 激活:

Dashboard → R2 → 按引导开通

需绑支付方式(免费额度内不产生费用:10 GB 存储 / 月、100 万次 A 类操作 / 月)。

未开通时 API 会拒绝:

代码
[code: 10042] Please enable R2 through the Cloudflare Dashboard.

2. 创建 bucket

bash
pnpm exec wrangler r2 bucket create saas-template-uploads

3. 配置绑定

wrangler.jsonc
{
  "r2_buckets": [{ "binding": "BUCKET", "bucket_name": "saas-template-uploads" }]
}

binding 是代码里读的名字(env.BUCKET),须与 src/types/cloudflare.d.ts 一致。

模板默认注释掉了该块——R2 需先 Dashboard 开通。开通后取消注释、重新部署即可。 未绑定时 env.BUCKET 为 undefined,getStorageProvider() 会抛错,这是预期的降级。

4. 启用文件上传

ts
// src/config/website.ts
features: {
  enableFileUpload: true,
}

改完重新构建并部署。

使用方法

所有函数从 @/storage 导入,内部经 AsyncLocalStorage 取当前请求的 provider:

ts
import { uploadFile, deleteFile, downloadFile, getFileInfo, listUserFiles } from '@/storage'

上传

ts
const result = await uploadFile(fileArrayBuffer, 'photo.png', 'image/png', {
  folder: 'uploads',        // 白名单:uploads / avatars / documents
  userId: 'user_abc',       // 可选,会进 key 路径
  visibility: 'private',    // 'private'(默认)| 'public'
})
// → { key, url, metadata }

key 形如 uploads/user_abc/1729000000000-photo.png。

删除与下载

这两个方法不检查文件所有权,调用方必须先确认 key 属于当前用户:

ts
await deleteFile(key, true)      // 第二参数 true = 已确认授权
await downloadFile(key, true)    // private 文件必须传 true

不传 authorized 会直接抛错——这是刻意的,防止忘记鉴权。

查询

ts
const info = await getFileInfo(key)          // { key, size, contentType, uploadedAt } | null
const { files, cursor } = await listUserFiles(userId)

安全约定

buildKey 对用户输入做净化:去除 /、\、.. 与前导 .,其余非法字符替换为 _; folder 仅接受白名单值;组装后再断言 key 以白名单前缀开头。

鉴权不在存储层。 deleteFile / downloadFile 只认 authorized 布尔值,不做任何 所有权查询。接上传接口时必须在调用前自行校验会话与归属,否则任何登录用户都能删改 他人文件。

命令

命令作用
pnpm exec wrangler r2 bucket create <name>创建 bucket
pnpm exec wrangler r2 bucket list列出 bucket
pnpm exec wrangler r2 object put <bucket>/<key> --file <path>上传对象

参考资料

下一步