【避坑指“难”】代码详解:阿里云oss上传视频,服务端签名后直传(vue+element-ui)

1,016 阅读1分钟

文档直达:服务端签名后直传

没有采用JS客户端签名直传上是因为,此过程AccessKey IDAcessKey Secret会暴露在前端页面,因此存在严重的安全隐患。所以查找阿里云决定使用服务端签名后直传的方案。

一、功能拆分

视频上传组件 el-upload:

<el-upload
          style="marginTop:-5px;"
          class="upload-demo"
          :action="ossParams.host || ''"
          :data="extraData"
          :before-upload="beforeUpload"
          :on-progress="handleUploadProgress"
          :on-success="handleUploadSuccess"
          :on-error="handleUploadError"
          :show-file-list="false"
          :disabled="uploadPercent > 0 && uploadPercent < 100"
          accept="video/*"
        >
          <el-button size="small" type="primary">{{
            uploadPercent === 0
              ? '点击上传'
              : uploadPercent === 100
              ? '重新上传'
              : '视频上传中,请稍候...'
          }}</el-button>
          <div slot="tip" class="el-upload__tip">
            支持所有视频文件,且不超过1GB
          </div>
</el-upload>

视频上传进度条el-progress:

<el-progress
          v-if="showPro"
          v-show="uploadPercent > 0"
          :percentage="uploadPercent"
          :color="customColorMethod"
></el-progress>

视频上传完成后显示的视频地址(可复制):

 <el-form-item v-if="uploadPercent === 100">
      <span style="font-size:12px;font-weight:500">视频地址 : </span>
      <el-link
        id="videoLink"
        :data-clipboard-text="'阿里云oss地址' + extraData.key"
        type="info"
        @click="
          () => {
            this.$message.success('复制视频地址成功')
          }
        "
        >{{ '阿里云oss地址' + extraData.key
        }}<i class="el-icon-document-copy el-icon--right"></i>
      </el-link>
    </el-form-item>

效果如下: 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

二、代码详解

1、el-upload组件

1)上传的地址 :action="ossParams.host || ''"

主要是获取上传阿里云的加密策略policy和签名signature,以及上传自己要上传到阿里云的地址,当然还有自己阿里云accessid。

2)上传时附带的额外参数:data="extraData" 参数如下:

extraData: {
        key: '',
        policy: '',
        OSSAccessKeyId: '',
        success_action_status: '200', //让服务端返回200,不然,默认会返回204
        callback: '',
        signature: ''
      }

3)上传前通过:before-upload="beforeUpload"进行校验:

beforeUpload(file) {
      if (file.size > 1024 * 1024 * 1024) {
        this.$message.error('上传视频大小不能超过1G')
        return false
      }
      const expire = this.ossParams.expire * 1000
      if (expire < Date.now() - 1000 * 60) {
        this.$message.error('token有效期已过期,请刷新页面重试')
        return false
      }
      this.uploadPercent = 0
      try {
        const { policy, accessid, dir, callback, signature } = this.ossParams
        const md5 = crypto.createHash('md5')
        const nameHash = md5
          .update(file.name.split('.')[0] + new Date().getTime().toString())
          .digest('hex')
        this.extraData.key = dir + nameHash + get_suffix(file.name)
        this.extraData.policy = policy
        this.extraData.OSSAccessKeyId = accessid
        this.extraData.callback = callback
        this.extraData.signature = signature
        return true
      } catch (err) {
        console.log(err)
        this.$message.error(err.message)
        return false
      }
    },

4)上传时:on-progress="handleUploadProgress"

 handleUploadProgress(event) {
      this.uploadPercent = parseInt(event.percent)
    },

5)上传成功 :on-success="handleUploadSuccess"

 handleUploadSuccess(response, file, fileList) {
      this.$message.success('视频上传成功')
      this.$nextTick(() => {
        const clipboard = new ClipboardJS('#videoLink')
      })
      console.log(response, file, fileList)
      this.uploadPercent === 100
        ? (this.showPro = false)
        : (this.showPro = true)
    },

6)上传失败 :on-error="handleUploadError"

 handleUploadError(err) {
      this.$message.error('视频上传失败 ' + err.toString())
      this.uploadPercent = 0
    },

2、el-progress组件 1)进度条百分比动态变色:color="customColorMethod"

customColorMethod(percentage) {
      if (percentage < 30) {
        return '#909399'
      } else if (percentage < 70) {
        return '#e6a23c'
      } else {
        return '#67c23a'
      }
    }

三、全部代码

在这里插入图片描述