对象存储最佳实践
1. 概念
对象存储(OSS / S3 / R2)= 无限容量的 KV 文件系统。前端用它存:
- 构建产物(JS/CSS/图片)— CDN 源站
- 用户上传文件(头像、附件)
- 备份、日志归档
2. 权限模型
2.1 公开读
静态资源(构建产物)用公开读:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-frontend-static/*"
}]
}
阿里云:Bucket ACL = 公共读。
2.2 私有 + 签名 URL
用户上传文件不能公开。需要时生成签名 URL(过期时间):
// AWS
const url = await getSignedUrl(s3, new GetObjectCommand({
Bucket: 'private-uploads',
Key: 'user/123/avatar.jpg',
}), { expiresIn: 3600 })
// 阿里
const url = client.signatureUrl('user/123/avatar.jpg', { expires: 3600 })
2.3 STS 临时凭证(前端直传)
后端签发临时 token,前端直传 OSS,不经过服务器。
// 后端(Node)
const { STS } = require('@alicloud/pop-core')
const sts = new STS({ ... })
const result = await sts.assumeRole(roleArn, policy, 900) // 15 分钟
res.json(result.Credentials)
// 前端
const client = new OSS({
accessKeyId: credentials.AccessKeyId,
accessKeySecret: credentials.AccessKeySecret,
stsToken: credentials.SecurityToken,
bucket: 'uploads',
})
await client.put(`user/${userId}/${filename}`, file)
3. CORS 配置
前端直传必须配 CORS:
[{
"AllowedOrigins": ["https://app.example.com"],
"AllowedMethods": ["GET", "PUT", "POST"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}]
4. 生命周期策略
自动清理旧文件、降存储级别:
{
"Rules": [{
"ID": "cleanup-old-builds",
"Prefix": "builds/",
"Status": "Enabled",
"Transitions": [
{ "Days": 30, "StorageClass": "STANDARD_IA" },
{ "Days": 90, "StorageClass": "GLACIER" }
],
"Expiration": { "Days": 365 }
}, {
"ID": "cleanup-temp",
"Prefix": "temp/",
"Expiration": { "Days": 7 }
}]
}
5. 版本控制
开启 versioning:误删可恢复。
aws s3api put-bucket-versioning --bucket my-bucket \
--versioning-configuration Status=Enabled
结合生命周期删旧版本:
{ "NoncurrentVersionExpiration": { "NoncurrentDays": 30 } }
6. 跨域资源加载
字体 / JS 跨域加载需要正确 CORS + 响应头:
Access-Control-Allow-Origin: *
CDN 配合 Vary: Origin 防缓存串。
7. 性能
- 分片上传:大文件(> 100MB)用 multipart upload
- 并发上传:小文件并发 10-20 个
- 就近访问:选近的 region / 开 CDN
- Transfer Acceleration:AWS S3 / 阿里 传输加速
8. 安全
- 不要开公开写:恶意上传
- STS 限 path 和权限:只能上传到自己目录
- 上传验证:文件类型白名单、大小限制
- 内容检测:图片鉴黄(云服务内容审核)
- 访问日志:开启 bucket 日志
- 加密:SSE-S3 / SSE-KMS 服务端加密
9. 常见反模式
- Bucket 公开写:被当免费图床
- STS 有效期 1 天:风险窗口太长。生产 15 分钟
- 不配生命周期:存储费年年涨
- 大文件不分片:超时 / 断点丢失
- 不配 CORS:前端直传报错
- 不开版本控制:误删无法恢复
- 日志存同一 bucket:循环记录