OSS服务端签名后直传

OSS服务端签名后直传

1.阿里云OSS启动器快速上手

  • 1)引入oss-starter

 // 1)引入oss-starter
 <dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>
  • 2)在配置文件中配置好ak、as、ep相关信息即可
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    alicloud:
      access-key: LTAI4Fym3yMo4wvUnn98yFuX
      secret-key: *********************
      oss:
        endpoint: oss-cn-hangzhou.aliyuncs.com
        bucket: mall-hugh
  application:
    name: cloud-third-party
  • 3)使用OSSClient 自动注入
	@Autowired
    OSS ossClient;

2.获取policy和签名的get请求接口

package com.linqibin.mall.thirdparty.controller;

import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.linqibin.common.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

@RestController
public class OSSController {
     

    @Autowired
    OSS ossClient;

    @Value("${spring.cloud.alicloud.access-key}")
    private String accessId;

    @Value("${spring.cloud.alicloud.secret-key}")
    private String accessKey;

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

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

    @RequestMapping("/oss/policy")
    public R policy() {
     
        // host的格式为 bucketname.endpoint
        String host = "https://" + bucket + "." + endpoint;
        // callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
        // String callbackUrl = "http://88.88.88.88:8888";

        // 用户上传文件时指定的前缀。
        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);
            // PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            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) {
     
            System.out.println(e.getMessage());
        }
        return R.ok().put("data", respMap);
    }
}

3.前端Vue上传组件

1)多文件上传

<template>
  <div>
    <el-upload
      action="http://mall-hugh.oss-cn-hangzhou.aliyuncs.com"
      :data="dataObj"
      list-type="picture-card"
      :file-list="fileList"
      :before-upload="beforeUpload"
      :on-remove="handleRemove"
      :on-success="handleUploadSuccess"
      :on-preview="handlePreview"
      :limit="maxCount"
      :on-exceed="handleExceed"
    >
      <i class="el-icon-plus">i>
    el-upload>
    <el-dialog :visible.sync="dialogVisible">
      <img width="100%" :src="dialogImageUrl" alt />
    el-dialog>
  div>
template>
<script>
import {
       policy } from "./policy";
import {
       getUUID } from '@/utils'
export default {
      
  name: "multiUpload",
  props: {
      
    //图片属性数组
    value: Array,
    //最大上传图片数量
    maxCount: {
      
      type: Number,
      default: 30
    }
  },
  data() {
      
    return {
      
      dataObj: {
      
        policy: "",
        signature: "",
        key: "",
        ossaccessKeyId: "",
        dir: "",
        host: "",
        uuid: ""
      },
      dialogVisible: false,
      dialogImageUrl: null
    };
  },
  computed: {
      
    fileList() {
      
      let fileList = [];
      for (let i = 0; i < this.value.length; i++) {
      
        fileList.push({
       url: this.value[i] });
      }

      return fileList;
    }
  },
  mounted() {
      },
  methods: {
      
    emitInput(fileList) {
      
      let value = [];
      for (let i = 0; i < fileList.length; i++) {
      
        value.push(fileList[i].url);
      }
      this.$emit("input", value);
    },
    handleRemove(file, fileList) {
      
      this.emitInput(fileList);
    },
    handlePreview(file) {
      
      this.dialogVisible = true;
      this.dialogImageUrl = file.url;
    },
    beforeUpload(file) {
      
      let _self = this;
      return new Promise((resolve, reject) => {
      
        policy()
          .then(response => {
      
            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);
          })
          .catch(err => {
      
            console.log("出错了...",err)
            reject(false);
          });
      });
    },
    handleUploadSuccess(res, file) {
      
      this.fileList.push({
      
        name: file.name,
        // url: this.dataObj.host + "/" + this.dataObj.dir + "/" + file.name; 替换${filename}为真正的文件名
        url: this.dataObj.host + "/" + this.dataObj.key.replace("${filename}",file.name)
      });
      this.emitInput(this.fileList);
    },
    handleExceed(files, fileList) {
      
      this.$message({
      
        message: "最多只能上传" + this.maxCount + "张图片",
        type: "warning",
        duration: 1000
      });
    }
  }
};
script>
<style>
style>


2)单文件上传组件

<template>
  <div>
    <el-upload
      action="http://mall-hugh.oss-cn-hangzhou.aliyuncs.com"
      :data="dataObj"
      list-type="picture"
      :multiple="false" :show-file-list="showFileList"
      :file-list="fileList"
      :before-upload="beforeUpload"
      :on-remove="handleRemove"
      :on-success="handleUploadSuccess"
      :on-preview="handlePreview">
      <el-button size="small" type="primary">点击上传el-button>
      <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过10MBdiv>
    el-upload>
    <el-dialog :visible.sync="dialogVisible">
      <img width="100%" :src="fileList[0].url" alt="">
    el-dialog>
  div>
template>
<script>
   import {
      policy} from './policy'
   import {
       getUUID } from '@/utils'

  export default {
      
    name: 'singleUpload',
    props: {
      
      value: String
    },
    computed: {
      
      imageUrl() {
      
        return this.value;
      },
      imageName() {
      
        if (this.value != null && this.value !== '') {
      
          return this.value.substr(this.value.lastIndexOf("/") + 1);
        } else {
      
          return null;
        }
      },
      fileList() {
      
        return [{
      
          name: this.imageName,
          url: this.imageUrl
        }]
      },
      showFileList: {
      
        get: function () {
      
          return this.value !== null && this.value !== ''&& this.value!==undefined;
        },
        set: function (newValue) {
      
        }
      }
    },
    data() {
      
      return {
      
        dataObj: {
      
          policy: '',
          signature: '',
          key: '',
          ossaccessKeyId: '',
          dir: '',
          host: '',
          // callback:'',
        },
        dialogVisible: false
      };
    },
    methods: {
      
      emitInput(val) {
      
        this.$emit('input', val)
      },
      handleRemove(file, fileList) {
      
        this.emitInput('');
      },
      handlePreview(file) {
      
        this.dialogVisible = true;
      },
      beforeUpload(file) {
      
        let _self = this;
        return new Promise((resolve, reject) => {
      
          // 服务端签名后直传,向后端发送一个get请求,获取policy,将policy封装进dataObj对象
          policy().then(response => {
      
            _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)
          }).catch(err => {
      
            reject(false)
          })
        })
      },
      handleUploadSuccess(res, file) {
      
        console.log("上传成功...")
        this.showFileList = true;
        this.fileList.pop();
        this.fileList.push({
      name: file.name, url: this.dataObj.host + '/' + this.dataObj.key.replace("${filename}",file.name) });
        this.emitInput(this.fileList[0].url);
      }
    }
  }
script>
<style>
style>



3)请求封装代码

import http from '@/utils/httpRequest.js'

export function policy () {
     
  return new Promise((resolve, reject) => {
     
    http({
     
      url: http.adornUrl('/thirdparty/oss/policy'),
      method: 'get',
      params: http.adornParams({
     })
    }).then(({
     data}) => {
     
      resolve(data)
    })
  })
}

4)axios封装

import Vue from 'vue'
import axios from 'axios'
import router from '@/router'
import qs from 'qs'
import merge from 'lodash/merge'
import {
      clearLoginInfo } from '@/utils'

const http = axios.create({
     
  timeout: 1000 * 30,
  withCredentials: true,
  headers: {
     
    'Content-Type': 'application/json; charset=utf-8'
  }
})

/**
 * 请求拦截
 */
http.interceptors.request.use(config => {
     
  config.headers['token'] = Vue.cookie.get('token') // 请求头带上token
  return config
}, error => {
     
  return Promise.reject(error)
})

/**
 * 响应拦截
 */
http.interceptors.response.use(response => {
     
  if (response.data && response.data.code === 401) {
      // 401, token失效
    clearLoginInfo()
    router.push({
      name: 'login' })
  }
  return response
}, error => {
     
  return Promise.reject(error)
})

/**
 * 请求地址处理
 * @param {*} actionName action方法名称
 */
http.adornUrl = (actionName) => {
     
  // 非生产环境 && 开启代理, 接口前缀统一使用[/proxyApi/]前缀做代理拦截!
  return (process.env.NODE_ENV !== 'production' && process.env.OPEN_PROXY ? '/proxyApi/' : window.SITE_CONFIG.baseUrl) + actionName
}

/**
 * get请求参数处理
 * @param {*} params 参数对象
 * @param {*} openDefultParams 是否开启默认参数?
 */
http.adornParams = (params = {
     }, openDefultParams = true) => {
     
  var defaults = {
     
    't': new Date().getTime()
  }
  return openDefultParams ? merge(defaults, params) : params
}

/**
 * post请求数据处理
 * @param {*} data 数据对象
 * @param {*} openDefultdata 是否开启默认数据?
 * @param {*} contentType 数据格式
 *  json: 'application/json; charset=utf-8'
 *  form: 'application/x-www-form-urlencoded; charset=utf-8'
 */
http.adornData = (data = {
     }, openDefultdata = true, contentType = 'json') => {
     
  var defaults = {
     
    't': new Date().getTime()
  }
  data = openDefultdata ? merge(defaults, data) : data
  return contentType === 'json' ? JSON.stringify(data) : qs.stringify(data)
}

export default http

你可能感兴趣的:(OSS,java学习笔记,vue,java)