阿里云OSS上传、下载、STS授权(Java篇)

声明:步骤比较长,如果你已经配置好OSS,直接拉到最后代码实现部分

1.申请oss,创建一个Bucket。

阿里云OSS上传、下载、STS授权(Java篇)_第1张图片

1)创建Bucket

阿里云OSS上传、下载、STS授权(Java篇)_第2张图片

2)红框内容建议选项,其余的随意

阿里云OSS上传、下载、STS授权(Java篇)_第3张图片

3)创建完成找到Bucket列表,选择刚创建的Bucket

阿里云OSS上传、下载、STS授权(Java篇)_第4张图片

4)绑定自己的域名(这一步可选,为了后期访问资源路径的统一性,记得打开CNANE选项)

阿里云OSS上传、下载、STS授权(Java篇)_第5张图片
阿里云OSS上传、下载、STS授权(Java篇)_第6张图片

2.创建RAM角色

1) 断点续传上传阿里云文档说明https://help.aliyun.com/document_detail/84785.html?spm=a2c4g.11186623.6.952.173c6d13b2BNrI

不过在这之前,我们的文件是以私有的方式访问的,所以在上传之前,先做STS临时访问权限的设置,当然你也可以选择公开,但建议最好选择私有
阿里云OSS上传、下载、STS授权(Java篇)_第7张图片

2)授权访问阿里云文档说明https://help.aliyun.com/document_detail/32016.html?spm=a2c4g.11186623.6.998.7ccb5d88coP9DG

授权的方式有两种,STS和URL两种方式,这里选择STS方式
阿里云OSS上传、下载、STS授权(Java篇)_第8张图片

3)在授权之前,我们先获取到STS临时访问凭证访问OSS

阿里云OSS上传、下载、STS授权(Java篇)_第9张图片

4)首先创建一个RAM用户(点击RAM控制台)

阿里云OSS上传、下载、STS授权(Java篇)_第10张图片

5)创建RAM

阿里云OSS上传、下载、STS授权(Java篇)_第11张图片

6)名称随意,但需要把Open API 调用访问勾选上

阿里云OSS上传、下载、STS授权(Java篇)_第12张图片

7)创建AccessKeyId(一个用户最多拥有两个AccessKeyId)

阿里云OSS上传、下载、STS授权(Java篇)_第13张图片

8)为RAM用户授予请求AssumeRole的权限

阿里云OSS上传、下载、STS授权(Java篇)_第14张图片

9)创建用于获取临时访问凭证的角色

阿里云OSS上传、下载、STS授权(Java篇)_第15张图片阿里云OSS上传、下载、STS授权(Java篇)_第16张图片

10)直接选择下一步

阿里云OSS上传、下载、STS授权(Java篇)_第17张图片

11)名称随意

阿里云OSS上传、下载、STS授权(Java篇)_第18张图片

12)创建完成之后,添加权限

AliyunOSSFullAccess对OSS全部操作权限
AliyunSTSAssumeRoleAccess调用STS服务AssumeRole接口的权限
AliyunUserOSS自定义策略权限
阿里云OSS上传、下载、STS授权(Java篇)_第19张图片

13)AliyunUserOSS配置,如果你不知道在写,就按照我的方式去配置

阿里云OSS上传、下载、STS授权(Java篇)_第20张图片

{
    "Version": "1",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "oss:*",
            "Resource": [
                "acs:oss:*:*:*"
            ]
        }
    ]
}

14)这一步就使用我们创建好的AliyunUserOSS配置

阿里云OSS上传、下载、STS授权(Java篇)_第21张图片

15)这步下面有代码不要急

阿里云OSS上传、下载、STS授权(Java篇)_第22张图片

16)这一步下面有代码,不要急

阿里云OSS上传、下载、STS授权(Java篇)_第23张图片

3.使用STS进行临时授权

1)添加依赖

java version>8

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.3</version>
</dependency>

java version <=8

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.10.2</version>
</dependency>

再添加lombok构造器注解依赖

	<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.20</version>
			<scope>provided</scope>
		</dependency>

重点来了,前面都是步骤,这里直接结合前面的步骤,代码实现

2)MD5Util.java用于加密文件名

import java.security.MessageDigest;

/**
 * MD5加密工具类
 */
public class MD5Util {
  /***
   * MD5加码 生成32位md5码
   */
  public static String getEncryptedPwd32(String inStr) {
    MessageDigest md5 = null;
    try {
      md5 = MessageDigest.getInstance("MD5");
    } catch (Exception e) {
      System.out.println(e.toString());
      e.printStackTrace();
      return "";
    }
    char[] charArray = inStr.toCharArray();
    byte[] byteArray = new byte[charArray.length];

    for (int i = 0; i < charArray.length; i++) byteArray[i] =
      (byte) charArray[i];
    byte[] md5Bytes = md5.digest(byteArray);
    StringBuffer hexValue = new StringBuffer();
    for (int i = 0; i < md5Bytes.length; i++) {
      int val = ((int) md5Bytes[i]) & 0xff;
      if (val < 16) hexValue.append("0");
      hexValue.append(Integer.toHexString(val));
    }
    return hexValue.toString();
  }

3)AliyunOSSFileConfig.java用于文件属性配置

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class AliyunOSSFileConfig {

  private String fileName;
  private String fileDir;
  private String fileType;

  public AliyunOSSFileConfig(String fileDir, String fileType) {
    this.fileDir = fileDir;
    this.fileType = fileType;
  }
  
  public AliyunOSSFileConfig(String fileName) {
    this.fileName = fileName;
  }
}

4)AliyunOSSConfig.java阿里云OSS配置

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class AliyunOSSConfig {

  /**
   * oss 访问地址
   */
  private String ossEndpoint = "步骤1.4创建的域名";
  /**
   * sts访问地址
   */
  private String stsEndpoint = "sts.cn-beijing.aliyuncs.com";
  /**
   * 请求标记符
   */
  private String requestId;
  /**
   * 安全令牌
   */
  private String securityToken;
  /**
   * 临时访问accessKeyId
   */
  private String accessKeyId = "步骤2.7创建的AccessKeyId";
  /**
   * 临时访问Secret
   */
  private String accessKeySecret = "步骤2.7创建的AccessKeySecret";
  /**
   * 有效时长(一天)
   */
  private long expiration = 3600L;
  /**
   * 角色ARN
   */
  private String roleArn = "复制步骤2.9的ARN值";
  /**
   * 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest。
   */
  private String roleSessionName = "英文字母随意";
  /**
   * oss bucket 名称
   */
  private String bucketName = "步骤1创建的Bucket";

  public AliyunOSSConfig(
    String accessKeyId,
    String accessKeySecret,
    String requestId,
    String securityToken
  ) {
    this.accessKeyId = accessKeyId;
    this.accessKeySecret = accessKeySecret;
    this.requestId = requestId;
    this.securityToken = securityToken;
  }
}

5)AliyunOSSUtils.java阿里云OSS上传,下载,STS,封装(步骤2.15,2.16的实现代码)

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.DownloadFileRequest;
import com.aliyun.oss.model.DownloadFileResult;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.UploadFileRequest;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class AliyunOSSUtils {

  /**
   * 实例化一个对象
   */
  private static AliyunOSSUtils instance;

  /**
   * oss参数配置
   */
  private static AliyunOSSConfig mConfig = new AliyunOSSConfig();

  /**
   * 创建一个实例
   * @return
   */
  public static AliyunOSSUtils getInstance() {
    if (instance == null) {
      instance = new AliyunOSSUtils();
    }
    return instance;
  }

  /**
   * 初始化oss配置
   * @param accessKeyId
   * @param accessKeySecret
   * @return
   * @throws Exception
   */
  public AliyunOSSUtils initConfig(AliyunOSSConfig config) throws Exception {
    if (instance == null) {
      throw new RuntimeException("请先调用getInstance来获取一个实例对象");
    }
    mConfig = config;
    return instance;
  }

  /**
   * 单文件上传
   * @param fileName
   * @return
   * @throws Throwable
   */
  public URL upload(AliyunOSSFileConfig fileConfig) {
    OSS ossClient = null;
    String oldFileName = fileConfig.getFileName();
    String fileDir = createFileDir(oldFileName);
    String fileName = createFileName(oldFileName);
    try {
      ossClient = getOSSClient();
      UploadFileRequest uploadFileRequest = getUploadFileRequest(
        mConfig.getBucketName(),
        oldFileName,
        fileDir + fileName
      );
      ossClient.uploadFile(uploadFileRequest);
    } catch (Throwable e) {
      e.printStackTrace();
    } finally {
      // 关闭OSSClient。
      ossClient.shutdown();
    }
    return getOSSFileUrl(ossClient, fileDir + fileName);
  }

  /**
   * 多个文件上传
   * @param file
   * @return
   * @throws Throwable
   */
  public List<URL> uploadMultipleFile(List<AliyunOSSFileConfig> list)
    throws Throwable {
    List<URL> urls = new ArrayList<>();
    OSS ossClient = getOSSClient();
    list.forEach(
      item -> {
        try {
          String oldFileName = item.getFileName();
          String fileDir = createFileDir(oldFileName);
          String fileName = createFileName(oldFileName);
          UploadFileRequest uploadFileRequest = getUploadFileRequest(
            mConfig.getBucketName(),
            oldFileName,
            fileDir + fileName
          );
          //上传文件
          ossClient.uploadFile(uploadFileRequest);
          urls.add(getOSSFileUrl(ossClient, fileDir + fileName));
        } catch (Throwable e) {
          e.printStackTrace();
          // 关闭OSSClient。
          ossClient.shutdown();
        }
      }
    );
    // 关闭OSSClient。
    ossClient.shutdown();
    return urls;
  }

  /**
   * 文件下载
   * @param fileName
   * @throws Throwable
   */
  public void download(String fileName, String dir) throws Throwable {
    if (
      fileName == null || fileName.isEmpty() || dir == null || dir.isEmpty()
    ) {
      throw new RuntimeException("请选择文件和储存路径");
    }
    // 创建OSSClient实例。
    OSS ossClient = getOSSClient();
    // 下载请求,10个任务并发下载,启动断点续传。
    DownloadFileRequest downloadFileRequest = new DownloadFileRequest(
      mConfig.getBucketName(),
      fileName
    );
    //文件后缀名
    String newFileName = createFileName(fileName);
    downloadFileRequest.setDownloadFile(dir + newFileName);
    downloadFileRequest.setPartSize(1 * 1024 * 1024);
    downloadFileRequest.setTaskNum(10);
    downloadFileRequest.setEnableCheckpoint(true);
    downloadFileRequest.setCheckpointFile("DownloadCheckpointFile");
    // 下载文件。
    DownloadFileResult downloadRes = ossClient.downloadFile(
      downloadFileRequest
    );
    // 下载成功时,会返回文件元信息。
    downloadRes.getObjectMetadata();
    // 关闭OSSClient。
    ossClient.shutdown();
  }

  /**
   *
   * @param endpoint STS接入地址 例如sts.cn-hangzhou.aliyuncs.com
   * @param roleArn 角色ARN。
   * @param roleSessionName 自定义角色会话名称,用来区分不同的令牌
   * @param accessKeyId 子账号accessKeyId
   * @param accessKeySecret 子账号accessKeySecret
   * @return
   */
  public AliyunOSSConfig getAssumeRole(
    String endpoint,
    String roleArn,
    String roleSessionName,
    String accessKeyId,
    String accessKeySecret
  ) {
    try {
      // 添加endpoint。
      DefaultProfile.addEndpoint("", "", "Sts", endpoint);
      // 构造default profile。
      IClientProfile profile = DefaultProfile.getProfile(
        "",
        accessKeyId,
        accessKeySecret
      );
      // 构造client。
      DefaultAcsClient client = new DefaultAcsClient(profile);
      final AssumeRoleRequest request = new AssumeRoleRequest();
      request.setMethod(MethodType.POST);
      request.setRoleArn(roleArn);
      request.setRoleSessionName(roleSessionName);
      request.setDurationSeconds(mConfig.getExpiration()); // 设置临时访问凭证的有效时间为3600秒。
      final AssumeRoleResponse response = client.getAcsResponse(request);
      //请求识别符号
      String requestId = response.getRequestId();
      //临时accessKeyId
      String tempAccessKeyId = response.getCredentials().getAccessKeyId();
      //临时accessKeySecret
      String tempAccessKeySecret = response
        .getCredentials()
        .getAccessKeySecret();
      //安全令牌
      String securityToken = response.getCredentials().getSecurityToken();
      return new AliyunOSSConfig(
        tempAccessKeyId,
        tempAccessKeySecret,
        requestId,
        securityToken
      );
    } catch (ClientException e) {
      System.out.println("Failed:");
      System.out.println("Error code: " + e.getErrCode());
      System.out.println("Error message: " + e.getErrMsg());
      System.out.println("RequestId: " + e.getRequestId());
      return null;
    }
  }

  /**
   * 获取上传后返回oss文件路径
   * @param oss 阿里云OSS
   * @param fileName 文件
   * @return
   */
  private URL getOSSFileUrl(OSS oss, String fileName) {
    //返回链接
    URL url = oss.generatePresignedUrl(
      mConfig.getBucketName(),
      fileName,
      new Date(new Date().getTime() + mConfig.getExpiration() * 1000)
    );
    // System.out.println("url====" + url);
    return url;
  }

  /**
   * 获取阿里云OSS
   * @param fileName 文件
   * @param securityToken 阿里云sts验证
   * @return
   * @throws Throwable
   */
  private OSS getOSSClient() throws Throwable {
    OSS ossClient = null;
    if (ossClient == null) {
      //设置ossClient配置
      ClientBuilderConfiguration clientConfig = new ClientBuilderConfiguration();
      //开启自定义域名
      clientConfig.setSupportCname(true);
      //获取临时凭证
      AliyunOSSConfig assumeRole = getAssumeRole(
        mConfig.getStsEndpoint(),
        mConfig.getRoleArn(),
        mConfig.getRoleSessionName(),
        mConfig.getAccessKeyId(),
        mConfig.getAccessKeySecret()
      );
      System.out.println(assumeRole);
      ossClient =
        new OSSClientBuilder()
        .build(
            assumeRole.getOssEndpoint(),
            assumeRole.getAccessKeyId(),
            assumeRole.getAccessKeySecret(),
            assumeRole.getSecurityToken(),
            clientConfig
          );
    }
    return ossClient;
  }

  /**
   * 获取oss文件上传工具
   * @param bucketName
   * @param fileName
   * @return
   */
  private UploadFileRequest getUploadFileRequest(
    String bucketName,
    String oldFileName,
    String fileName
  ) {
    UploadFileRequest uploadFileRequest = null;
    if (uploadFileRequest == null) {
      ObjectMetadata meta = new ObjectMetadata();
      AliyunOSSFileConfig fileConfig = getContentType(oldFileName);
      meta.setContentType(fileConfig.getFileType());
      uploadFileRequest = new UploadFileRequest(bucketName, fileName);
      // 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
      uploadFileRequest.setUploadFile(oldFileName);
      // 指定上传并发线程数,默认值为1。
      uploadFileRequest.setTaskNum(5);
      // 指定上传的分片大小。
      uploadFileRequest.setPartSize(1 * 1024 * 1024);
      // 开启断点续传,默认关闭。
      uploadFileRequest.setEnableCheckpoint(true);
      // 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中。
      uploadFileRequest.setCheckpointFile("UploadCheckpointFile");
      // 文件的元数据。
      uploadFileRequest.setObjectMetadata(meta);
    }
    return uploadFileRequest;
  }

  /**
   * 获取临时文件资源路径
   * @param fileName (目录+文件名称 例:image/2021-08-05/126cb28e1f9422a4410a6b76bda28be6.jpg)
   * @return
   * @throws Throwable
   */
  public String getFileUrl(String fileName) throws Throwable {
    URL url = getOSSFileUrl(getOSSClient(), fileName);
    String path = url.toString();
    return path;
  }

  /**
   * 通过文件名判断并获取OSS服务文件上传时文件的contentType
   */
  private static AliyunOSSFileConfig getContentType(String fileName) {
    String fileExtension = getSuffix(fileName);
    if (".bmp".equalsIgnoreCase(fileExtension)) {
      return new AliyunOSSFileConfig("image/", "image/bmp");
    }
    if (".gif".equalsIgnoreCase(fileExtension)) {
      return new AliyunOSSFileConfig("image/", "image/gif");
    }
    if (".jpeg".equalsIgnoreCase(fileExtension)) {
      return new AliyunOSSFileConfig("image/", "image/jpeg");
    }
    if (".jpg".equalsIgnoreCase(fileExtension)) {
      return new AliyunOSSFileConfig("image/", "image/jpg");
    }
    if (".png".equalsIgnoreCase(fileExtension)) {
      return new AliyunOSSFileConfig("image/", "image/png");
    }
    if (".html".equalsIgnoreCase(fileExtension)) {
      return new AliyunOSSFileConfig("txt/", "text/html");
    }
    if (".txt".equalsIgnoreCase(fileExtension)) {
      return new AliyunOSSFileConfig("txt/", "text/plain");
    }
    if (".vsd".equalsIgnoreCase(fileExtension)) {
      return new AliyunOSSFileConfig("doc/", "application/vnd.visio");
    }
    if (
      ".ppt".equalsIgnoreCase(fileExtension) ||
      "pptx".equalsIgnoreCase(fileExtension)
    ) {
      return new AliyunOSSFileConfig("doc/", "application/vnd.ms-powerpoint");
    }
    if (
      ".doc".equalsIgnoreCase(fileExtension) ||
      "docx".equalsIgnoreCase(fileExtension)
    ) {
      return new AliyunOSSFileConfig("doc/", "application/msword");
    }
    if (".xml".equalsIgnoreCase(fileExtension)) {
      return new AliyunOSSFileConfig("doc/", "text/xml");
    }
    if (".mp4".equalsIgnoreCase(fileExtension)) {
      return new AliyunOSSFileConfig("video/", "video/mp4");
    }
    if (".mp3".equalsIgnoreCase(fileExtension)) {
      return new AliyunOSSFileConfig("audio/", "audio/mp3");
    }
    return new AliyunOSSFileConfig("other/", "text/html");
  }

  /**
   * 获取文件后缀名
   * @param fileName
   * @return
   */
  private static String getSuffix(String fileName) {
    if (fileName != null && !fileName.isEmpty()) {
      return fileName.substring(fileName.lastIndexOf("."));
    }
    return "";
  }

  /**
   * 生成文件名称
   * @param fileName
   * @return
   */
  private static String createFileName(String fileName) {
    //随机生成六位验证码
    int code = (int) ((Math.random() * 9 + 1) * 100000);
    //通过md5加密文件
    String newFileName = MD5Util.getEncryptedPwd32(fileName + code);
    //文件后缀名
    String suffix = getSuffix(fileName);
    return newFileName + suffix;
  }

  /**
   * 创建文件目录
   * @param fileName
   * @return
   */
  private static String createFileDir(String fileName) {
    //获取当前日期
    String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
    //文件目录
    AliyunOSSFileConfig fileConfig = getContentType(fileName);
    String fileDir = fileConfig.getFileDir();
    return fileDir + date + "/";
  }
}

4.使用方法

1)单文件上传

    String file =
      "/Applications/Developer/icloud/java/mybatis-plus/src/main/resources/static/2021.jpg";
    AliyunOSSUtils.getInstance().upload(new AliyunOSSFileConfig(file));

阿里云OSS上传、下载、STS授权(Java篇)_第24张图片

2)多文件上传(结果就不展示了)

  List<AliyunOSSFileConfig> list = new ArrayList<>();
    list.add(
      new AliyunOSSFileConfig(
        "/Applications/Developer/icloud/java/mybatis-plus/src/main/resources/static/2021.jpg"
      )
    );
    list.add(
      new AliyunOSSFileConfig(
        "/Applications/Developer/icloud/java/mybatis-plus/src/main/resources/static/cpop.jpeg"
      )
    );
AliyunOSSUtils.getInstance().uploadMultipleFile(list);

3)下载文件(String fileName(文件名包含目录), String dir(下载之后保存的目录)))

  AliyunOSSUtils.getInstance().download("image/2021-08-05/1dbb650b9f6d42ec2cbdc12a07da68e2.jpg","/Applications/Developer/icloud/java/mybatis-plus/src/main/resources/static/");

4)获取指定文件的临时访问路径

    AliyunOSSUtils.getInstance().getFileUrl(
      "video/2021-08-05/d53bb0bd3aa4fb5ae4aabfd4514f2842.mp4"
    );

按照上面的步骤一步步配置,代码直接复制开箱使用,切记一定要注意细节

你可能感兴趣的:(java,阿里云,java,阿里云,oss,文件上传,文件下载)