记录一下 用ElementUI里的upload组件上传到阿里的OSS

项目场景:

一、当我们再做微服务项目的时候,之前上传的文件都是存到本地,当我们服务多了之后,一个机器将不够用,因此我们需要部署到多个机器,如果一个服务挂了恰好也是刚刚上传的文件的服务,当网关去找这个服务的时候找不到,因此会负载均衡找到别的服务,但是那个服务却没有我们所上传的文件,所以我们需要一个云存储,这里我们选择阿里的OSS对象存储服务。

1、首先需要去阿里云开通OSS对象存储服务,开通后是这样的
在这里插入图片描述2、建立一个bucket(存储对象的容器,上边的jdmall-upload就是建立的一个bucket)点进所建立的bucket之后进入上传文件的地方,当然肯定不是在这上边上传,我们需要结合前端页面使用elementUi来上传然后与后端联调完成上传文件
在这里插入图片描述
3、使用ElementUi的图片缩略图的upload组件
在这里插入图片描述
这里主要注意action属性,点击上传后会走这个url还有下边几个回调函数,上传之前、上传成功、上传失败这几个回调函数,这里就不介绍了直接上代码。

<template>
  <div>
    <el-upload
      action="http://jdmall-upload.oss-cn-beijing.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文件,且不超过10MB</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 !== '') {
        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) => {
        console.log('文件名:', file)
        policy().then(response => {
          _self.dataObj.policy = response.data.policy
          _self.dataObj.signature = response.data.signature
          _self.dataObj.ossaccessKeyId = response.data.accessid
          // eslint-disable-next-line no-template-curly-in-string
          _self.dataObj.key = response.data.dir + getUUID() + '_' + file.name
          _self.dataObj.dir = response.data.dir
          _self.dataObj.host = response.data.host
          console.log('响应的数据。。。', _self.dataObj)
          resolve(true)
        })
      })
    },
    handleUploadSuccess (res, file) {
      console.log('上传成功...')
      this.showFileList = true
      this.fileList.pop()
      // eslint-disable-next-line no-template-curly-in-string,standard/object-curly-even-spacing
      this.fileList.push({name: file.name, url: this.dataObj.host + '/' + this.dataObj.key})
      this.emitInput(this.fileList[0].url)
    }
  }
}
</script>
<style>
</style>

这里主要 介绍几个参数:
:on-preview=“handlePreview”:指的是上传之后的文件列表里得东西
:file-list=“fileList”:是缩略图,具体格式请查看官方
action: 是上传的地址
:data=“dataObj” 上传成功之后数据存到这里是个对象

二、至于上传的地址为什么是这个样子的具体我们看后端:

1、首先我们应导入OSS相应的依赖:

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>aliyun-oss-spring-boot-starter</artifactId>
        </dependency>
        
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.4.5</version>
        </dependency>

我建议是最好导入这俩个依赖,反正aliyun-oss-spring-boot-starter这个是必须导入的,下边那个依赖依据自己情况,我没导的时候反正报错。

2、我们需要去配置OSS,配置上传的地址呀,账号密码啥的,一般 微服务都会配置到nacos配置中心
在这里插入图片描述
access-key: 就是账号
secret-key: 就是密码
endpoint: 是地域节点,就是上传到哪里

至于怎么创建oss的access-key和secret-key,自己去百度搜索吧。
最好在创建AccessKey的时候把跨域勾上,然后设置一些权限
在这里插入图片描述
在这里插入图片描述
设置完跨域后,,新建AccessKey:
新建AccessKey:
在这里插入图片描述
进入AccessKey界面创建完毕后:
在这里插入图片描述

设置权限策略:
在这里插入图片描述
3、这样全部配置完了之后开始编写签名对象,签名对象就是将我们在nacos配置中心里配置的accessKey全部封装起来,然后传给前端,浏览器在进行解析,直接上代码:
(1) 我们引入了相应的oss依赖之后,直接注入
@Autowired
OSS ossClient;
我们使用阿里提供这个对象来编写oss签名
(2) 通过@Value 注解来拿取nacos配置中心中的信息,最终封装起来返回给前端
代码详情参考:Web端上传,服务签名直传并设置回调

@RestController
//制作oss签名方法,再返回给前端
    @RequestMapping("thirdService")
public class OssController {
    @Value("${alibaba.cloud.oss.endpoint}")
    private String endpoint;
    @Value("${alibaba.cloud.oss.bucket}")
    private String bucket;

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

    @Autowired
    OSS ossClient;
//生成签名对象,包含oss账号密码返回给浏览器,浏览器 通过这个对象上传到oss
    @RequestMapping("/oss/qianM")
    public R qianming(){
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        // 填写Bucket名称,例如examplebucket。
//        String bucket = "jdmall-upload";
        // 填写Host名称,格式为https://bucketname.endpoint。
        //https://jdmall-upload.oss-cn-beijing.aliyuncs.com/testImage.jpg
        String host = "https://"+ bucket + "." + endpoint;
        // 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。
//        String callbackUrl = "https://192.168.0.0:8888";
        // 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
        //以日期的方式作为前缀
        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) {
            // Assert.fail(e.getMessage());
            System.out.println(e.getMessage());
        }

        return R.ok("上传成功").put("data",respMap);
    }

}

三、回到前端

    <el-upload
      action="buket地址"
      :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文件,且不超过10MB</div>
    </el-upload>

这段代码的action属性就指的是,我们bucket对象存储容器的地址:
在这里插入图片描述
上传之前我们调用这个函数,上传之前就发送上传的请求:
**:before-upload=“beforeUpload”,**我们使用了promise对象,为了更方便快速的响应。

 beforeUpload (file) {
      let _self = this
      return new Promise((resolve, reject) => {
        console.log('文件名:', file)
        policy().then(response => {
          _self.dataObj.policy = response.data.policy
          _self.dataObj.signature = response.data.signature
          _self.dataObj.ossaccessKeyId = response.data.accessid
          // eslint-disable-next-line no-template-curly-in-string
          _self.dataObj.key = response.data.dir + getUUID() + '_' + file.name
          _self.dataObj.dir = response.data.dir
          _self.dataObj.host = response.data.host
          console.log('响应的数据。。。', _self.dataObj)
          resolve(true)
        })
      })

我们看一下上传之后的响应数据:
在这里插入图片描述
这就是我们后端封装的oss签名对象,返回给前端的数据,我就不把数据展开看了。

以下是上传成功之后的回调:

 handleUploadSuccess (res, file) {
      console.log('上传成功...')
      this.showFileList = true
      this.fileList.pop()
      // eslint-disable-next-line no-template-curly-in-string,standard/object-curly-even-spacing
      this.fileList.push({name: file.name, url: this.dataObj.host + '/' + this.dataObj.key})
      this.emitInput(this.fileList[0].url)
    }
  }

前边beforeUpload这个回调已经将数据返回存到了dataObj,因此我们直接拿来用放到fileList里边,做缩略图。

最后讲一下OSS里URL的组成:

Bucket域名+后端自己封装的dir + getUUID() + ‘_’ + file.name

这是bucket上传成功之后的图片的url:
在这里插入图片描述

后端自己封装的dir,以日期格式作为文件夹
在这里插入图片描述
最终返回给前端
在这里插入图片描述
之前上传成功后的文件:
在这里插入图片描述
在这里插入图片描述

小弟新手,纯属记录自己代码日常,以防忘记,大佬勿喷!!

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值