SpringBoot 整合阿里云存储OSS

此次整合采用 ali-OSS 提供的服务端签名后直传的方案

——原理

  1. 用户发送上传 Policy 请求到应用服务器
  2. 应用服务器返回上传 Policy 和签名给用户
  3. 用户直接上传数据到 OSS

——整合

  • pom.xml
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
  • application.properties
spring.cloud.alicloud.access-key=yourAk
spring.cloud.alicloud.secret-key=yourSk
spring.cloud.alicloud.oss.endpoint=***
spring.cloud.alicloud.oss.bucket=***
  • 获取签名
@Slf4j
@RestController
public class OssController {
    @Autowired
    OSS ossClient;
    @Value ("${spring.cloud.alicloud.oss.endpoint}")
    String endpoint ;

    @Value("${spring.cloud.alicloud.oss.bucket}")
    String bucket ;

    @Value("${spring.cloud.alicloud.access-key}")
    String accessId ;
    @Value("${spring.cloud.alicloud.secret-key}")
    String accessKey ;
    
    @RequestMapping("/oss/policy")
    public R policy(){
    	// host的格式为 bucketname.endpoint
        String host = "https://" + bucket + "." + endpoint; 
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dir = format; // 用户上传文件时指定的前缀。

        Map<String, String> respMap=null;
        try {
            // 签名有效事件
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            // 签名
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            respMap= new LinkedHashMap<String, String>();
            respMap.put("accessid", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));

        } catch (Exception e) {
        	log.warn("获取签名异常");
        } finally {
            ossClient.shutdown();
        }
        // R 是返回数据的格式
        return R.ok.put("data",respMap);
    }
}
  • 返回数据格式 R 类
public class R extends HashMap<String, Object> {
	private static final long serialVersionUID = 1L;
	
	public R() {
		put("code", 0);
		put("msg", "success");
	}
	
	public static R error() {
		return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
	}
	
	public static R error(String msg) {
		return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
	}
	
	public static R error(int code, String msg) {
		R r = new R();
		r.put("code", code);
		r.put("msg", msg);
		return r;
	}

	public static R ok(String msg) {
		R r = new R();
		r.put("msg", msg);
		return r;
	}
	
	public static R ok(Map<String, Object> map) {
		R r = new R();
		r.putAll(map);
		return r;
	}
	
	public static R ok() {
		return new R();
	}

	public R put(String key, Object value) {
		super.put(key, value);
		return this;
	}
}
  • 返回签名的结果格式
{
  "accessid": "LTAI4G3ewgWMxsrnaaeDuT1B",
  "policy": "eyJleHBpcmF0aW9uIjoiMjAyMS0wMi0xNFQxMDoyOToxMS43ODhaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCIyMDIxLTAyLTE0Il1dfQ==",
  "signature": "0OXDXrQ1vRNl61N5IaZXRFckCKM=",
  "dir": "2021-02-14",
  "host": "https://gulimall-fermhan.oss-cn-qingdao.aliyuncs.com",
  "expire": "1613298551"
}
  • 阿里云存储开启跨域
    在这里插入图片描述
  • 结合 element-ui 组件完成上传功能
 <el-upload
      drag
      :action="endpointUrl"
      :before-upload="beforeUploadHandle"
      :on-success="successHandle"
      multiple
      :file-list="fileList"
      style="text-align: center;">
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
      <div class="el-upload__tip" slot="tip">只支持jpg、png、gif格式的图片!</div>
    </el-upload>
  • 上传前 :before-upload 方法的实现
// 获取服务端的签名数据
function policy() {
   return  new Promise((resolve,reject)=>{
        http({
            // 先去获取签名
            url: http.adornUrl("/third/party/oss/policy"),
            method: "get",
            params: http.adornParams({})
        }).then(({ data }) => {
            // 然后拿着签名去请求数据
            resolve(data);
        })
    });
}
// 上传文件前的检验
beforeUpload(file) {
      let _self = this;
      return new Promise((resolve, reject) => {
          
        policy() // 获取签名后得到相应
          .then(response => {
            // 意思是说policy获取到签名后,把签名信息保存起来
            // console.log("这是什么${filename}");
            _self.dataObj.policy = response.data.policy;
            _self.dataObj.signature = response.data.signature;
            _self.dataObj.ossaccessKeyId = response.data.accessid;
            _self.dataObj.key = response.data.dir +getUUID()+"_${filename}";
            _self.dataObj.dir = response.data.dir;
            _self.dataObj.host = response.data.host;
            resolve(true);
            // 总的来说什么意思呢?
            // 上传之前先请求签名,保存起来签名
            // 根据action="http://gulimall-fermhan.oss-cn-qingdao.aliyuncs.com"
            // 结合data信息,提交到云端
          })
          .catch(err => {
            console.log("出错了...",err)
            reject(false);
          });
      });
    },
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序少年不秃头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值