对象存储

对象存储

存储模块提供统一对象接口、预签名上传和图片代理。生成时选择 S3 Compatible 或 Cloudflare 原生 R2 Binding。

适配器

选择配置运行环境
s3-compatibleSTORAGE_ENDPOINTSTORAGE_REGIONSTORAGE_BUCKET_NAME、Access Key/SecretServer、Docker、Vercel
r2-bindingNEXTDEVTPL_STORAGE R2 BindingCloudflare Workers

头像 bucket 由 NEXT_PUBLIC_AVATARS_BUCKET_NAME 指定。未设置上传 bucket 时, 通用上传默认使用 nextdevtpl-uploads,生产环境建议显式配置。

上传流程

  1. 浏览器向 /api/upload/presigned 请求上传信息。
  2. 服务端检查登录状态、文件类型、大小和 object key。
  3. S3 组合返回预签名 URL,浏览器直传对象存储。
  4. 应用保存 object key,通过 /image-proxy/... 或受控 URL 读取。

R2 Binding 在 Worker 请求期间延迟注入,业务代码继续通过 storageService 调用。

主要代码

路径作用
src/core/services/storage.ts统一对象存储接口
src/adapters/storageS3 和 R2 实现
src/services/storage.ts当前存储实例
src/app/api/upload/presigned/route.ts上传入口
src/app/image-proxy/[...path]/route.ts受控图片读取

安全检查

  • Bucket 默认保持私有,限制 CORS 到应用域名。
  • 在签名或写入前校验文件类型、大小和用户作用域。
  • object key 使用不可预测值,禁止接收任意路径穿越片段。
  • Access Key 只放服务端,R2 Binding 权限缩到所需 bucket。
  • 修改后运行 pnpm test:run -- src/test/storage/security.test.ts

本页目录