1. 阿里云OSS设置
-
登录aliyun:www.aliyun.com/?utm_conten…
-
进入aliyun控制台
-
进入OSS控制台
-
新建Bucket
Bucket为OSS的存储空间,在上传数据(例如文档、图片、音视频等)到OSS之前,您需要在OSS所支持的地域中创建一个存储空间(Bucket),然后将无限数量的对象(Object)上传到该Bucket中。
-
输入Bucket信息
2. 上传默认头像
-
进入Bucket,新建一个目录
-
进入该目录,点击上传文件
-
选择文件上传
-
将默认头像的URL作为数据库avatar字段的默认值
3. 获取AccessKeys
-
进入AccessKeys管理
-
开始使用子用户AccessKeys
阿里云给每一个账户提供一个全局的AccessKey,但是如果该AccessKey泄露,那么该用户在阿里云上所拥有的所有产品的使用权限都会暴露出去。所以选择使用子用户的AccessKey,来讲所有的使用权限细分,每一个阿里云的业务都可以定制独立的AccessKey。
-
创建用户组
-
添加用户
-
将用户添加进入用户组
-
给用户组分配权限
还可以给每一个用户分配权限,一般比较简单的项目只需要给用户组分配权限即可。
-
获取AccessKey
AccessKey获取后需要保存起来,如果丢失,重新创建一个新的AccessKey即可。
4. OSS环境配置
-
服务中引入OSS依赖
<!-- 阿里云对象存储 --> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>2.8.3</version> </dependency>
-
查看endpoint
-
查看accessKeyId和access
见3.7
-
查看bucketName
-
服务的application.yml添加配置
# 阿里云oss配置
aliyun:
oss:
file:
bucketname: postilhub
endpoint: oss-cn-beijing.aliyuncs.com
keyid: xxxxxxxxxxxxx
keysecret: xxxxxxxxxxxxx
filehost: avatar
-
服务中创建constant包
-
constant中创建常量配置类
@Component
public class OSSConstant implements InitializingBean {
@Value("${aliyun.oss.file.bucketname}")
private String bucketName;
@Value("${aliyun.oss.file.endpoint}")
private String endpoint;
@Value("${aliyun.oss.file.keyid}")
private String keyId;
@Value("${aliyun.oss.file.keysecret}")
private String keySecret;
@Value("${aliyun.oss.file.filehost}")
private String fileHost;
public static String BUCKET_NAME;
public static String ENDPOINT;
public static String ACCESS_KEY_ID;
public static String ACCESS_KEY_SECRET;
public static String FILE_HOST;
// 读取配置文件后做的系统配置,将配置文件的内容赋值给静态常量
@Override
public void afterPropertiesSet() throws Exception {
BUCKET_NAME = this.bucketName;
ENDPOINT = this.endpoint;
ACCESS_KEY_ID = this.keyId;
ACCESS_KEY_SECRET = this.keySecret;
FILE_HOST = this.fileHost;
}
}
5. 实现头像上传
OSS文档:help.aliyun.com/document_de…
5.1 UserController.java
注意,此处上传文件,文件参数前添加的注解为@RequestParam("avatar"),为什么不是@RequestBody?
以为使用POST上传文件时,只能使用POST方式中的form-Data来上传,不能使用POST方式中的Body(Json)来上传。
@ApiOperation(value = "上传用户头像")
@PostMapping("uploadAvatar")
public Response uploadAvatar(
@ApiParam(name = "avatar", value = "用户头像文件", required = true)
@RequestParam("avatar") MultipartFile avatar,
@RequestHeader("Authorization") String token) {
// 从Token中获取用户id
DecodedJWT decodedJWT = JWTUtils.verifyToken(token);
String id = decodedJWT.getClaim("id").asString();
try {
String avatarUrl = userService.uploadAvatar(id, avatar);
return Response.ok().message("上传头像成功").data("avatarUrl", avatarUrl);
} catch (IOException e) {
throw new AvatarUploadException(ResponseEnum.AVATAR_UPLOAD_ERROR);
// return Response.error(ResponseEnum.AVATAR_UPLOAD_ERROR);
}
}
5.2 UserService.java
/**
* OSS上传头像
* @param avatar 头像文件
* @param id 用户id
* @return 头像文件在bucket中中的绝对路径
*/
String uploadAvatar(String id, MultipartFile avatar) throws IOException;
/**
* OSS删除头像
* @param bucketName bucketName
* @param objectName 头像文件在bucket中的相对路径
*/
void deleteAvatar(String bucketName, String objectName);
5.3 UserServiceImpl.java
@Override
public String uploadAvatar(String id, MultipartFile avatar) throws IOException {
// 初始化oss参数
String bucketName = OSSConstant.BUCKET_NAME;
String endpoint = OSSConstant.ENDPOINT;
String accessKeyId = OSSConstant.ACCESS_KEY_ID;
String accessKeySecret = OSSConstant.ACCESS_KEY_SECRET;
String fileHost = OSSConstant.FILE_HOST;
// 头像文件在网络中的地址(服务器上的绝对地址)
String avatarUrl = "";
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
// 判断该bucket是否存在
if (!ossClient.doesBucketExist(bucketName)) {
// 使用aliyun接口创建bucket
ossClient.createBucket(bucketName);
// 设置bucket权限:公共读
ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
}
// 获取上传文件流
InputStream inputStream = avatar.getInputStream();
// 原始头像文件名
String originalAvatarName = avatar.getOriginalFilename();
// 头像文件类型
String avatarType = originalAvatarName.substring(originalAvatarName.lastIndexOf(".") + 1);
// 头像上传至bucket的文件名
String avatarName = UUID.randomUUID().toString() + avatarType;
// 头像文件在bucket上的相对路径(使用jodatime添加三级目录,每一天更新一个文件夹,提高运行效率)
String avatarRelativePath = fileHost + "/" + new DateTime().toString("yyyy/MM/dd") + "/" + avatarName;
// 上传文件至bucket
ossClient.putObject(bucketName, avatarRelativePath, inputStream);
// 关闭OSSClient
ossClient.shutdown();
// 组装头像文件在bucket上的绝对路径: https://bucketName + . + endpoint/avatarRelativeUrl
avatarUrl = "https://" + bucketName + "." + endpoint + "/" + avatarRelativePath;
User user = userMapper.selectById(id);
// 如果不是第一次上传头像,在bucket中删除原头像文件
if (user.getAvatarRelativePath() != null) {
deleteAvatar(bucketName, user.getAvatarRelativePath());
}
// 将新avatar的绝对路径和相对路径更新进数据库
user.setAvatar(avatarUrl);
user.setAvatarRelativePath(avatarRelativePath);
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", id);
userMapper.update(user, updateWrapper);
return avatarUrl;
}
@Override
public void deleteAvatar(String bucketName, String objectName) {
String endpoint = OSSConstant.ENDPOINT;
String accessKeyId = OSSConstant.ACCESS_KEY_ID;
String accessKeySecret = OSSConstant.ACCESS_KEY_SECRET;
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
ossClient.deleteObject(bucketName, objectName);
ossClient.shutdown();
}