阿里OSS基本使用

时间:2024-02-18 11:43:08

阿里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");