Arclovia 文档
功能与集成

Storage (R2)

基于 Cloudflare R2 的私有对象存储。普通素材和头像都走 浏览器直传:文件字节不会经过 Worker,Worker 只负责签发短期 PUT URL、校验完成结果和提供读取路由。

上传链路

  1. 浏览器调用 createUploadUrl,服务端校验声明的 MIME/大小,生成 assets/<userId>/<uuid>avatars/<userId>/<uuid>,并创建 status='pending' 的 asset 行。头像用 source='avatar' 区分,不会混入普通素材库。
  2. Worker 用 R2 S3 API credentials 签发 15 分钟有效的预签名 PUT URL;Content-Type 被写入 SigV4 签名。浏览器随后直接 PUT 到 R2。
  3. 浏览器调用 completeUpload。服务端用 R2 binding HEAD 对象,核对实际大小和 Content-Type,再以 compare-and-set 把行切到 ready

所有 key 都由服务端生成且每次上传不同。user.image 仍是稳定读取路径 /api/avatars/<userId>?v=<assetId>;读取路由通过 asset 行解析真正的随机 R2 key。 读取路由还兼容旧版本的数字时间戳 ?v=<Date.now()>,此时回退读取原固定 key,因而上线 不需要迁移现有头像;用户下次上传后会自然切到新格式。

计划任务会清理两类对象:超过 1 小时仍未完成的直传,以及保留 7 天后已被替换的头像历史。 当前头像永远不会因年龄被删除;异步生成视频虽然也使用 pending,但 source='generated' 不会进入直传清理范围。

本地配置

R2 binding 在 miniflare 测试里可直接使用,但浏览器直传需要真实的 R2 S3 endpoint 和 credentials。在 .dev.vars 配齐以下五项;五项全空时直传会优雅关闭:

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=auto
AWS_ENDPOINT_URL_S3=https://<accountId>.r2.cloudflarestorage.com
S3_BUCKET=flarestarter-files

API token 只授予目标 bucket 的 Object Read & Write 权限。AWS_SECRET_ACCESS_KEY 不要写进 wrangler.jsonc 或提交到 Git。

Bucket CORS(必需)

浏览器访问预签名 URL 仍受 CORS 约束。复制 r2-cors.example.json,把 https://example.com 改成真实站点 origin(只有 scheme、host 和可选 port,不要带路径), 然后对每个环境的 bucket 应用:

npx wrangler r2 bucket cors set flarestarter-files --file r2-cors.example.json
npx wrangler r2 bucket cors set flarestarter-files-staging --file r2-cors.example.json
npx wrangler r2 bucket cors set flarestarter-files-prod --file r2-cors.example.json

规则只开放 PUTContent-Type。没有这条 CORS policy 时,签名本身即使正确,浏览器 直传也会失败。

部署

首次部署先创建三个 bucket:

npx wrangler r2 bucket create flarestarter-files
npx wrangler r2 bucket create flarestarter-files-staging
npx wrangler r2 bucket create flarestarter-files-prod

再为相应命名环境写入 S3 credentials。生产环境示例:

npx wrangler secret put AWS_ACCESS_KEY_ID --env production
npx wrangler secret put AWS_SECRET_ACCESS_KEY --env production
npx wrangler secret put AWS_REGION --env production
npx wrangler secret put AWS_ENDPOINT_URL_S3 --env production
npx wrangler secret put S3_BUCKET --env production

最后应用上面的 CORS policy。读取仍经过 Worker 的 /api/assets/*/api/avatars/*, 无需把 bucket 设为 public。

安全边界

  • client 的 MIME/大小声明先按头像或素材白名单校验;key 永远由服务端生成。
  • SigV4 把 PUT method、对象 key、过期时间和 Content-Type 固定下来。
  • completeUpload 不接受 client 提供的 kind,而从 DB source 判定 avatar;并以 R2 HEAD 的真实 metadata 做最终大小/类型校验。
  • 普通素材读取和删除都排除 avatar 行;素材读取还要求 owner session。

On this page