阿里云oss对象存储访问的使用

  1. 创建阿里云OSS对象存储服务
    在这里插入图片描述
  • 创建bucket存储空间
    在这里插入图片描述
  • 创建RAM子用户Accesskey进行API调用(安全性考虑)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 添加权限
    在这里插入图片描述
  • 创建跨域规则解决跨域问题
    在这里插入图片描述
  1. 代码有关操作
  • 引入阿里云oss依赖

    <!--        使用阿里云的oss对象存储服务-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
    </dependency>
    
  • 在yml中配置oss相关信息

    spring:
      cloud:
        alicloud:
          # RAM子用户账号
          access-key: 
          # RAM子用户密码
          secret-key: 
          oss:
         	# 地址节点
            endpoint: 
    
  • 在应用服务器使用OSSClient进行相关操作(应用服务器负载太大)

    @SpringBootTest
    @Slf4j
    class GulimallProductApplicationTests {
          
          
    	@Autowired
    	private BrandService brandService;
    
    	@Autowired
    	OSSClient ossClient;
    
    	@Test
    	void testUpload() throws FileNotFoundException {
          
          
    		// 上传文件流。
    		InputStream inputStream = new FileInputStream("/Users/zhaolijian/Projects/springCloud_learning/miaosha/html/static/assets/global/plugins/fancybox/demo/3_b.jpg");
    		ossClient.putObject("gulimall-zlj", "3_b.jpg", inputStream);
    
    		// 关闭OSSClient。
    		ossClient.shutdown();
    		System.out.println("上传完成");
    	}
    
  1. 使用签名(policy策略)方式上传
    在这里插入图片描述
  • 使用签名上传策略原因
    采用JavaScript客户端直接签名时,AccessKey ID和AcessKey Secret会暴露在前端页面,因此存在严重的安全隐患。因此,OSS提供了服务端签名后直传的方案。
    本示例中,Web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但本示例中的服务端无法实时了解用户上传了多少文件,上传了什么文件。如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。

  • 后端代码: 获取签名

    package com.kenai.gulimall.thirdparty.controller;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.OSSClient;
    import com.aliyun.oss.common.utils.BinaryUtil;
    import com.aliyun.oss.model.MatchMode;
    import com.aliyun.oss.model.PolicyConditions;
    import com.kenai.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
    @RequestMapping("oss")
    public class OssController {
          
          
    
        @Autowired
        private OSS ossClient;
    
        @Value("${spring.cloud.alicloud.oss.endpoint}")
        private String endpoint;
    
        @Value("${spring.cloud.alicloud.oss.bucket}")
        private String bucket;
    
        @Value("${spring.cloud.alicloud.access-key}")
        private String accessId;
    
        @RequestMapping("/policy")
        public R policy(){
          
          
            String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.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);
                PolicyConditions policyConds = new PolicyConditions();
                //允许上传的文件大小限制: CONTENT_LENGTH_RANGE为5*1024*1024*1024=5G
                policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
                // 上传目录
                policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
                //给policyConds添加过期时间并json序列化(格式iso8601:"yyyy-MM-dd'T'HH:mm:ss.fff'Z'")
                String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
                byte[] binaryData = postPolicy.getBytes("utf-8");
                //  将policy的json字符串进行base64编码
                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));
                // respMap.put("expire", formatISO8601Date(expiration));
            } catch (Exception e) {
          
          
                // Assert.fail(e.getMessage());
                System.out.println(e.getMessage());
            } finally {
          
          
                ossClient.shutdown();
            }
            return R.ok().put("data", respMap);
        }
    }
    
  • policy.js(前端请求签名代码)

    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)
        })
      })
    }
    
  • singleUpload.vue(前端单文件上传代码)

    <template>
      <div>
        <!-- list-type: 	文件列表的类型 -->
        <!-- multiple: 是否支持多选文件 -->
        <!-- show-file-list: 是否显示已上传文件列表 -->
        <!-- file-list: 上传的文件列表 -->
        <!-- before-upload: 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。 -->
        <!-- on-remove: 文件列表移除文件时的钩子 -->
        <!-- on-success: 文件上传成功时的钩子 -->
        <!-- on-preview: 点击文件列表中已上传的文件时的钩子 -->
        <el-upload
          action="http://gulimall-zlj.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文件,且不超过5MB</div>
        </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 !== '') {
           
           
            // 截取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
        },
        // 在上传之前向应用服务器请求policy签名
        beforeUpload (file) {
           
           
          let _self = this
          return new Promise((resolve, reject) => {
           
           
            // response为Promise异步请求调用成功后resolve回调函数中的data
            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
                console.log('响应的数据', _self.dataObj)
                resolve(true)
              })
              .catch(err => {
           
           
                console.log('错误信息', err)
                reject(new Error(false))
              })
          })
        },
        handleUploadSuccess (res, file) {
           
           
          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>
    
  • multiUpload.vue(前端多文件上传代码)

    <template>
      <div>
        <el-upload
          action="http://gulimall-zlj.oss-cn-hangzhou.aliyuncs.com"
          :data="dataObj"
          :list-type="listType"
          :file-list="fileList"
          :before-upload="beforeUpload"
          :on-remove="handleRemove"
          :on-success="handleUploadSuccess"
          :on-preview="handlePreview"
          :limit="maxCount"
          :on-exceed="handleExceed"
          :show-file-list="showFile"
        >
          <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
        },
        listType:{
           
           
          type: String,
          default: "picture-card"
        },
        showFile:{
           
           
          type: Boolean,
          default: true
        }
      },
      data() {
           
           
        return {
           
           
          dataObj: {
           
           
            policy: "",
            signature: "",
            key: "",
            ossaccessKeyId: "",
            dir: "",
            host: "",
            uuid: ""
          },
          dialogVisible: false,
          dialogImageUrl: null
        };
      },
    //  computed用来监控自己定义的变量fileList, 当this.value发生变化时,fileList也发生变化
      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>
    

猜你喜欢

转载自blog.csdn.net/qq_26496077/article/details/114259219