对象存储
对象存储
存储模块提供统一对象接口、预签名上传和图片代理。生成时选择 S3 Compatible 或 Cloudflare 原生 R2 Binding。
适配器
| 选择 | 配置 | 运行环境 |
|---|---|---|
s3-compatible | STORAGE_ENDPOINT、STORAGE_REGION、STORAGE_BUCKET_NAME、Access Key/Secret | Server、Docker、Vercel |
r2-binding | NEXTDEVTPL_STORAGE R2 Binding | Cloudflare Workers |
头像 bucket 由 NEXT_PUBLIC_AVATARS_BUCKET_NAME 指定。未设置上传 bucket 时,
通用上传默认使用 nextdevtpl-uploads,生产环境建议显式配置。
上传流程
- 浏览器向
/api/upload/presigned请求上传信息。 - 服务端检查登录状态、文件类型、大小和 object key。
- S3 组合返回预签名 URL,浏览器直传对象存储。
- 应用保存 object key,通过
/image-proxy/...或受控 URL 读取。
R2 Binding 在 Worker 请求期间延迟注入,业务代码继续通过 storageService 调用。
主要代码
| 路径 | 作用 |
|---|---|
src/core/services/storage.ts | 统一对象存储接口 |
src/adapters/storage | S3 和 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。