阿里OSS使用
一、安装
第一步要进行安装阿里OSS,导入依赖
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
二、创建存储空间
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
String bucketName = "<yourBucketName>";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 创建存储空间。
ossClient.createBucket(bucketName);
// 关闭OSSClient。
ossClient.shutdown();
这里要在阿里云官网设置RAM访问权限,添加用户以及用户组,设置好了之后就可以进行使用了
首先进入到管理控制台,点击这个RAM,顺便提一句,RAM就是在阿里oos里面是分权限的Access Key是最高权限什么都可以使用,如果要单独访问一个功能使用Access Key就很不安全,所以单独制定一个权限的话就用RAM就很好
点开RAM就要创建一个用户
点击用户
可以创建用户,用这个用户去操作咱们的oos
设置好基本信息就可以正常使用了
成功后记得下载好基本信息,下一步就是为这个用户设置权限,权限的话以分组为例
点击用户组,在点击创建用户组
输入基本信息即可
点击添加权限
选择自己所需要的权限即可
把用户添加到用户组中,就可以了
三、配置yaml
alioss:
endpoint: oss-cn-qingdao.aliyuncs.com
accessKeyId: LTAI4GGDjTZg133jzdRPR5AF
accessKeySecret: GzhuSGouMhEtpwFbFV90IhdLDgshte
bucketName: mjy-test
四、新建实体类
@Data
public class OssEntity {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
}
需要将这个类交给spring管理
@Component//只需要在类上加上这个注解即可
然后要读取yaml文件,也是用一个注解就可以扫描的到
@ConfigurationProperties(prefix = "alioss")
五、测试,值有没有拿到
直接写一个测试方法即可
@SpringBootTest(classes = XinguanBaseWebApplication.class)
public class OssTest {
@Autowired
private OssEntity ossEntity;
@Test
void ossTest(){
System.out.println(ossEntity.toString());
}
}
六、编写Service以及实现类(创建存储空间)
public interface AliOssService {
/**
* 创建存储空间
*/
void createBucket();
/**
* 上传文件
* @param file 文件对象
* @return
*/
String upload(MultipartFile file);
/**
* 下载文件
* @param fileName
* @throws IOException
*/
void download(String fileName)throws IOException;
/**
* 列举文件
*/
void listFile();
/**
* 删除文件
* @param fileName
*/
void deleteFile(String fileName);
}
5个方法来实现的功能就是上传头像的功能
下面是实现类的代码
/**
* 在创建这个AliOssServiceImpl的时候就应该把属性值装载
*
* @author sfybxs
*/
@Service
public class AliOssServiceImpl implements AliOssService, InitializingBean {
@Autowired
private OssEntity ossEntity;
/**
* Endpoint以杭州为例,其它Region请按实际情况填写
*/
private String endpoint;
/**
* 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。
* 强烈建议您创建并使用RAM账号进行API访问或日常运维,
* 请登录RAM控制台创建RAM账号。
*/
private String accessKeyId;
/**
* 密钥
*/
private String accessKeySecret;
/**
* <yourObjectName>上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
*/
private String bucketName;
/**
* 初始化bean之后需要进行的操作
*
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
// Endpoint以杭州为例,其它Region请按实际情况填写。
endpoint = ossEntity.getEndpoint();
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
accessKeyId = ossEntity.getAccessKeyId();
accessKeySecret = ossEntity.getAccessKeySecret();
bucketName = ossEntity.getBucketName();
}
/**
* 创建存储空间
*/
@Override
public void createBucket() {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 创建存储空间。
ossClient.createBucket(bucketName);
// 关闭OSSClient。
ossClient.shutdown();
}
/**
* 上传文件
*
* @param file 文件对象
* @return
*/
@Override
public String upload(MultipartFile file) {
return null;
}
/**
* 下载文件
*
* @param fileName
* @throws IOException
*/
@Override
public void download(String fileName) throws IOException {
}
/**
* 列举文件
*/
@Override
public void listFile() {
}
/**
* 删除文件
*
* @param fileName
*/
@Override
public void deleteFile(String fileName) {
}
}
报错
com.aliyun.oss.common.auth.InvalidCredentialsException: Access key id should not be null or empty.
根本问题在于没有值,经过测试OssEntity是可以拿到yaml的值的问题在于赋值
@Override
public void afterPropertiesSet() throws Exception {
// Endpoint以杭州为例,其它Region请按实际情况填写。
endpoint = ossEntity.getEndpoint();
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
accessKeyId = ossEntity.getAccessKeyId();
accessKeySecret = ossEntity.getAccessKeySecret();
bucketName = ossEntity.getBucketName();
}
这是正确的方法,错误方法是把这些值都从定义了一个变量导致拿到的值为空
测试了创建存储空间的方法是ok没有问题的
如果是你的Bucket名字已经存在怎么办,就可以加上一个判断
//判断bucketName是否存在
if (ossClient.doesBucketExist(bucketName)){
throw new RuntimeException(bucketName+"在对象存储的Bucket列表中已经存在");
}
七、编写Service以及实现类(文件上传)
/**
* 上传文件
*
* @param file 文件对象
* @return
*/
@Override
public String upload(MultipartFile file) {
//上传地址
String uploadUrl = null;
try {
//创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
//判断bucketName是否存在
if (!ossClient.doesBucketExist(bucketName)) {
//创建bucket
ossClient.createBucket(bucketName);
//设置bucket的属性
ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
}
//获取上传的文件流
InputStream inputStream = file.getInputStream();
//构建日期的文件夹路径
String datePath = new DateTime().toString("yyyy/MM/dd");
//获取上传文件的全名称
String original = file.getOriginalFilename();
//获取uuid,因为uuid中间是用-相连接,要用replaceAll方法来去除-
String fileName = UUID.randomUUID().toString().replaceAll("-", "");
//获取上传文件的扩展名
String fileType = original.substring(original.lastIndexOf("."));
//拼接文件名称
String newName = fileName + fileType;
//生成文件夹
fileName = datePath + "/" + newName;
//如果想要实现图片预览的效果,一定要设置以下几点
/**
* 1.设置文件的ACL(权限)要么是公共读,要么是公共读写
* 2.一定要设置文本类型(image/jpg)
*/
ObjectMetadata objectMetadata = new ObjectMetadata();
//设置公共读权限
objectMetadata.setObjectAcl(CannedAccessControlList.PublicRead);
//设置文本类型
objectMetadata.setContentType(getcontentType(fileType));
//每次上传得到的名字肯定是不能相同的,在java中如何让每次生成的名字不一样呢
//uuid 为了更加方便的区分,这边的文件格式yyyy/MM/dd+uuid
ossClient.putObject(bucketName, fileName, inputStream, objectMetadata);
//关闭OSSClient
ossClient.shutdown();
//默认十年不过期
Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
//bucket名称 文件名 过期时间
uploadUrl = ossClient.generatePresignedUrl(bucketName, fileName, expiration).toString();
} catch (Exception e) {
e.printStackTrace();
}
return uploadUrl.substring(0, uploadUrl.indexOf("?"));
}
这里关于访问路径不能预览的问题,参考我另一篇专门的博客
八、jodatime包
导入依赖
<!--日期格式转换-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.9</version>
</dependency>
用处可以构建你想要的文件夹类型
//构建日期的文件夹路径
String datePath = new DateTime().toString("yyyy/MM/dd");