Java+vue3实现阿里云oss后端签名前端上传

739 阅读2分钟

后端环境:java8、spring boot、jdk1.8.191

前端环境:vue3.2、vite4.3、axios1.3 (Geeker Admin初始化框架)

项目思路:前端上传文件使用el-upload的http-request事件覆盖默认xhr行为,手动请求后端签名接口获取签名,通过axios直接将文件上传到阿里云。

一、阿里云配置
  1. 使用RAM访问控制,创建子用户后保存AccessKey、AccessKey ID
  2. Bucket数据安全设置跨域来源为服务器前端地址,例:http://127.0.0.1:8080
二、后端签名
  1. 创建AliyunConfig类保存阿里云配置参数
public class AliyunConfig {  
    // RAM用户AccessKey ID
    public static final String accessId = "*****";  
    // RAM用户AccessKey
    public static final String accessKey = "*****";  
    // bucket地域地址
    public static final String endpoint = "oss-cn-guangzhou.aliyuncs.com"; 
    // bucke名称
    public static final String bucket = "bucket_name";  
    // 使用bucke名称 + bucket地域地址组合成前端上传地址
    public static final String host = "https://bucket_name.oss-cn-guangzhou.aliyuncs.com";
    // 文件存放目录
    public static final String dir = "";  
}
  1. 签名接口
@RestController  
@RequestMapping("/upload")  
public class OSSController {  
  
    @GetMapping(value = "/get/signature")  
        // 创建OSS客户端,使用AliyunConfig中指定的endpoint、accessId和accessKey  
        OSS ossClient = new OSSClientBuilder().build(AliyunConfig.endpoint, AliyunConfig.accessId, AliyunConfig.accessKey);  

        long expireTime = 30L;  
        long expireEndTime = System.currentTimeMillis() + expireTime * 1000;  
        Date expiration = new Date(expireEndTime);  
        // 设置PostObject请求的条件,其中COND_CONTENT_LENGTH_RANGE表示文件大小范围,此处设置为0到1048576000字节(即1GB)  
        PolicyConditions policyConds = new PolicyConditions();  
        policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);  
        policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, AliyunConfig.dir);  

        String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);  
        byte[] binaryData = new byte[0];  
        binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);  
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);  
        String postSignature = ossClient.calculatePostSignature(postPolicy);  

        // 构造返回的OSS签名信息对象  
        AliyunOssSignature res = new AliyunOssSignature(AliyunConfig.accessId, encodedPolicy, postSignature, AliyunConfig.dir, AliyunConfig.host, String.valueOf(expireEndTime / 1000),null); 

        ossClient.shutdown();  

        return ResponseResult.success(res);  
    } 
  
}
三、前端上传

1、获取签名接口

export namespace Upload {
  export interface ResSignature {
    accessid: string;
    policy: string;
    signature: string;
    dir: string;
    host: string;
    expire: string;
    callback: string;
  }
}

export const getUploadSignature = () => {
  return http.get<Upload.ResSignature>("/upload/get/signature");
};

2、使用el-upload上传

<el-upload 
:http-request="handleHttpUpload"> 
    <!-- 其他配置项 --> 
</el-upload>

const handleHttpUpload = async (options: UploadRequestOptions) => {
  let formData = new FormData();
  const filename = `${generateUUID()}${options.file.name}`;
  formData.append("key", filename);
  formData.append("file", options.file);

  try {
    const ossConfig = await getUploadSignature();
    const { accessid, policy, signature, host } = ossConfig.data;
    formData.append("OSSAccessKeyId", accessid);
    formData.append("policy", policy);
    formData.append("signature", signature);
    await axios.post(host, formData, {
      headers: {
        "Content-Type": "multipart/form-data"
      }
    });

    ...
  } catch (error) {
    ...
  }
};

前端具体框架封装请查看(Geeker Admin初始化框架) UploadImg组件,只需修改handleHttpUpload方法即可