S3 对象存储
Cloudflare R2/S3 的 CORS、密钥变量、签名上传 URL 与头像代理访问配置指南。
MuseMVP 封装了通用 S3 协议的文件上传接口,无缝兼容 AWS S3、Cloudflare R2 或自建 MinIO。当前主要用于用户头像上传,可按需扩展至其他文件类型。
配置步骤
配置跨域

[
{
"AllowedOrigins": [
"*"
],
"AllowedMethods": [
"GET",
"POST",
"PUT",
"DELETE",
"HEAD"
],
"AllowedHeaders": [
"*"
],
"ExposeHeaders": [
"ETag"
],
"MaxAgeSeconds": 3600
}
]提示
配置跨域是为了让前端可以访问 Cloudflare R2 存储桶,请根据实际需求修改,尤其是 AllowedOrigins 需要根据实际需求修改。
创建 S3_ACCESS_KEY_ID、S3_SECRET_ACCESS_KEY 和 S3_ENDPOINT

S3_ACCESS_KEY_ID="55xxxc34b0"
S3_SECRET_ACCESS_KEY="08xxx625b1cc0cbe"
S3_ENDPOINT="https://xxx.r2.cloudflarestorage.com"图片代理前缀
- 创建一个Worker,具体参考 Cloudflare R2 proxyUrls脚本
export const config = {
storage: {
proxyUrls: {
avatarsFile: resolveUrlValue(
process.env.NEXT_PUBLIC_AVATARS_PROXY_URL,
"",
),
},
},
};上传对象路径规则
头像上传采用两层路径结构:
- 前端传入相对路径(
path),例如:2026_02_18_avatar_xxx.png - 后端统一加用户目录前缀(
userId)作为最终对象 key
最终 key 格式:${userId}/${path}
示例:
userId = user_abc123path = 2026_02_18_avatar_3f2c...png- 对象存储 key =
user_abc123/2026_02_18_avatar_3f2c...png
每位用户的静态资源落在自己的 userId 目录下,便于按用户维度检索、迁移与清理。
代理前缀与访问 URL
UserAvatar 组件有两种头像地址处理方式:
avatarUrl以http开头:直接使用(完整外链)- 其他情况:按
${config.storage.proxyUrls.avatarsFile}/${avatarUrl}拼接
推荐配置
将 config.storage.proxyUrls.avatarsFile(或 NEXT_PUBLIC_AVATARS_PROXY_URL)指向 CDN 或对象存储的公开读域名,例如 https://static.example.com。
必填存储环境变量
以下 3 个变量必须同时存在,否则后端不会签发上传 URL:
| 变量名 | 说明 |
|---|---|
S3_ACCESS_KEY_ID | S3 兼容服务的 Access Key |
S3_SECRET_ACCESS_KEY | S3 兼容服务的 Secret Key |
S3_ENDPOINT | 服务端点(如 https://xxx.r2.cloudflarestorage.com) |
当缺失时:
- 后端返回
503,错误码STORAGE_ENV_MISSING - 前端头像上传会触发 warning toast,并提示缺失变量名
相关配置项
src/config/index.ts 的 storage 分区:
| 配置项 | 说明 |
|---|---|
storage.meta | S3 服务端连接参数 |
storage.bucketNames.avatars | 头像 bucket(支持 NEXT_PUBLIC_AVATARS_BUCKET_NAME 覆盖) |
storage.proxyUrls.avatarsFile | 头像访问前缀域名(支持 NEXT_PUBLIC_AVATARS_PROXY_URL 覆盖) |


