这里整理一下项目中关于 OSS 对象存储的接入记录。主要目的是解决文件上传和访问速率的问题,当然也可以存数据库,但考虑到性能和成本,OSS 是更优解。简单做个备忘。
OSS 基础配置(官方详细解决方案:https://www.aliyun.com/product/oss)
1.1 创建Bucket
登录阿里云控制台,进入 OSS 管理界面后,点击“创建 Bucket”。具体的配置项如下,按实际项目需求填写:
Bucket 名称:air-test1
地域:选择 杭州 (oss-cn-hangzhou),尽量选离服务器或用户最近的地域以降低延迟。
存储类型:标准存储(适合频繁读写的场景)。
读写权限:
这里选了 公共读。
注意:如果选择了公共读,图片/文件可以直接通过 URL 访问;如果不希望公开,需要改用私有读写,并在前端请求时配合签名 URL 使用。
版本控制:按需开启(一般测试环境可不选)。
服务端加密:按需开启(敏感数据建议开启,普通静态资源可不开)。
1.2 创建后设置
关闭阻止公共访问
读写权限:公共读
1.3 访问密钥配置
在阿里云控制台获取 AccessKey:
1、AccessKey ID
2、AccessKey Secret
出于安全考虑,建议:
1、使用 RAM 用户创建 AccessKey
2、只授予必要的 OSS 权限
3、定期轮换 AccessKey
4、创建RAM用户并授予对应的权限
进入用户管理控制台
创建用户,输入对应的名称就可以了(需要验证)

点击创建的用户,创建AccessKey(记住创建的AccessKey ID和AccessKey Secret)

1.4 项目配置
OSS地域和访问域名
配置系统变量ALIBABA_AIR_TEST1_ACCESSKEY_ID和ALIBABA_AIR_TEST1_ACCESSKEY_SECRET(对应的值就设置成上面的AccessKey ID和AccessKey Secret)
在 application.yml 中配置 OSS 参数:
oss:
endpoint: oss-cn-hangzhou.aliyuncs.com
accessKeyId: ${ALIBABA_AIR_TEST1_ACCESSKEY_ID}
accessKeySecret: ${ALIBABA_AIR_TEST1_ACCESSKEY_SECRET}
bucketName: air-test1
urlPrefix: https://air-test1.oss-cn-hangzhou.aliyuncs.com/
环境变量配置:
```export ALIBABA_AIR_TEST1_ACCESSKEY_ID=your_access_key_id
export ALIBABA_AIR_TEST1_ACCESSKEY_SECRET=your_access_key_secret
2. 代码实现
``` <!-- 阿里云OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
2.1 OSS 配置类
public class OSSConfig {
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.accessKeyId}")
private String accessKeyId;
@Value("${aliyun.oss.accessKeySecret}")
private String accessKeySecret;
@Value("${aliyun.oss.bucketName}")
private String bucketName;
@Bean
public OSS ossClient() {
return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
}
}
2.2 OSS 工具类
public class AliOSSUtils {
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.accessKeyId}")
private String accessKeyId;
@Value("${aliyun.oss.accessKeySecret}")
private String accessKeySecret;
@Value("${aliyun.oss.bucketName}")
private String bucketName;
/**
* 上传文件到OSS
* @param file 要上传的文件
* @param directory 存储的目录(可选,如:avatars/)
* @return 文件访问URL
*/
public String uploadFile(MultipartFile file, String directory) throws IOException {
// 获取上传的文件的输入流
InputStream inputStream = file.getInputStream();
// 生成唯一文件名
String originalFilename = file.getOriginalFilename();
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
String fileName = (directory != null ? directory : "") + UUID.randomUUID().toString() + extension;
// 创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 上传文件到OSS
ossClient.putObject(bucketName, fileName, inputStream);
// 构建文件访问路径
return "https://" + bucketName + "." + endpoint + "/" + fileName;
} finally {
// 关闭OSSClient
if (ossClient != null) {
ossClient.shutdown();
}
// 关闭输入流
if (inputStream != null) {
inputStream.close();
}
}
}
/**
* 上传图片到OSS(简化方法,不指定目录)
*/
public String uploadImage(MultipartFile file) throws IOException {
return uploadFile(file, "images/");
}
/**
* 上传头像到OSS
*/
public String uploadAvatar(MultipartFile file) throws IOException {
return uploadFile(file, "avatars/");
}
}
- 使用说明
3.1 代码使用示例
上传头像:
```@Autowired
private AliOSSUtils aliOSSUtils;
public String uploadAvatar(MultipartFile file) {
try {
return aliOSSUtils.uploadAvatar(file);
} catch (IOException e) {
throw new RuntimeException("上传头像失败", e);
}
}
```
安全与规范建议
访问控制(重中之重)
拒绝 Root Key:绝对不要用主账号 AK/SK 写代码。务必创建 RAM 用户,遵循最小权限原则。
移动端/前端上传:严禁在前端硬编码 AccessKey。必须使用 STS 临时凭证方案,后端签发短效 Token 给前端,既安全又灵活。
定期轮换:养成习惯,定期更换 AccessKey,防止泄露风险。数据安全
防盗链:配置 Referer 白名单,防止资源被其他网站恶意引用消耗流量。
跨域设置 (CORS):根据业务需求精准配置 CORS 规则,不要为了省事直接 Allow-Origin: *,除非是纯公开静态资源。
加密存储敏感数据开启服务端加密(SSE)。文件管理规范
目录结构:按 业务线/年份/月份/ID 规范命名,方便后续检索和清理。
生命周期:务必配置 Lifecycle 规则,自动删除日志、临时文件或过期的非热数据,省钱利器。
常见问题排查 (FAQ)
上传失败?先查这几点:
Endpoint:检查是否配错了地域(比如 Bucket 在杭州,却用了北京 Endpoint)。
AK/SK:确认密钥是否有效,是否有对应 Bucket 的操作权限。
Bucket 名称:拼写错误是低级但高发的错误。常见报错码对照:
InvalidAccessKeyId:AK 无效或已被禁用。
SignatureDoesNotMatch:签名算法错误,或者客户端与服务端时间不同步(NTP 问题),或者是 SecretKey 填错。
NoSuchBucket:Bucket 不存在或名称拼写错误。
AccessDenied:权限不足(RAM 策略没配好,或 Bucket 是私有读写)。权限层级理解:
Bucket 级别:
私有:必须带签名 URL 才能访问(推荐用于私密数据)。
公共读:URL 直链访问(推荐用于图片、JS/CSS 等公开资源)。
公共读写:强烈不建议开启,等于把大门敞开给黑客。
文件级别:可以单独设置某个文件的权限覆盖 Bucket 默认值,但管理成本高,建议统一用 Bucket 权限,除非有特殊合规要求。性能优化思路:
客户端大文件上传必做 断点续传;图片上传后利用 OSS 自带的图片处理服务(缩略图、水印)节省带宽。
服务端尽量复用连接,异步处理耗时任务(如生成视频封面),不要阻塞主线程。
监控与维护
核心监控指标
别只看“存了多少”,要关注:
请求次数 & 流量统计:突然暴涨可能意味着被攻击或异常下载。
返回码分布:重点盯着 4xx 和 5xx 错误率。
存储用量:监控增长趋势,避免预算超支。成本控制
设置报警阈值:当月流量或存储量达到预警线时,第一时间收到通知。
阶梯定价:对于冷数据,及时转为低频访问或归档存储类型,成本能降一个数量级。日常维护清单
定期查看访问日志,分析热点文件。
清理不再使用的测试 Bucket 和废弃文件。
每半年审查一次 RAM 用户的权限分配。
参考文档:https://www.aliyun.com/product/oss/features/vector-bucket