VUE-阿里云OSS上传组件

根据项目需求封装的一个阿里云OSS上传组件,可进行图片上传和视频上传。

上组件代码:

<template>
  <div>
    <div v-if="uploadType == 'image'">
      <el-upload
        class="avatar-uploader"
        :style="{ width: imgWidth + 'px', height: imgHeight + 'px' }"
        action=""
        :show-file-list="false"
        :auto-upload="false"
        :on-change="(file) => uploadImageOrVideo(file)"
      >
        <img
          v-if="showUrl"
          :src="OSSUrl(showUrl)"
          class="avatar"
          :style="{ width: imgWidth + 'px', height: imgHeight + 'px' }"
        />
        <i
          v-else
          class="el-icon-plus avatar-uploader-icon"
          :style="{
            width: imgWidth + 'px',
            height: imgHeight + 'px',
            'line-height': imgHeight + 'px',
          }"
        ></i>
      </el-upload>
    </div>
    <div v-if="uploadType == 'video'" class="video-main">
      <el-upload
        v-show="!uploadProgress"
        style="display: inline-block"
        action=""
        :multiple="false"
        :auto-upload="false"
        :show-file-list="false"
        :on-change="(file) => uploadImageOrVideo(file)"
      >
        <el-button
          style="margin-left: 10px"
          type="normal"
          size="small"
          @click="uploadBefore"
          >选择视频</el-button
        >
      </el-upload>

      <el-button
        v-if="!showProgress && uploadProgress"
        style="margin-left: 10px"
        type="normal"
        size="small"
        >视频上传中...</el-button
      >
      <div style="width: 150px" v-if="uploadProgress && showProgress">
        <el-progress
          :text-inside="true"
          :stroke-width="20"
          :percentage="uploadProgress"
        ></el-progress>
      </div>
      <el-button
        v-if="uploadProgress && cancelUpload"
        style="margin-left: 10px"
        type="normal"
        size="small"
        @click="stopUpload"
        >取消上传</el-button
      >
      <el-button
        v-show="showUrl && !uploadProgress && videoPreview"
        style="margin-left: 10px"
        type="normal"
        size="small"
        @click="dialogVisible = true"
        >视频预览</el-button
      >
    </div>
    <el-dialog title="视频预览" :visible.sync="dialogVisible" width="650px">
      <video
        controls
        :src="OSSUrl(showUrl)"
        style="width: 600px; height: 400px"
      />
    </el-dialog>
  </div>
</template>
<script>
// 下载oss模块后,引入使用
import OSS from 'ali-oss'
let clientArr = []
export default {
  props: {
    uploadType: {//上传的类型:image-图片(默认),video-视频
      type: String,
      default: 'image'
    },
    showFileUrl: {//要显示的image/video在阿里云服务器上的地址
      type: String,
      default: ''
    },
    configureOSS: {//创建OSS实例所需的配置项: 示例:{region:'oss-cn-shenzhen',accessKeyId:'xxx',accessKeySecret:'xxx',stsToken:'xxx',timeout:'xxx',bucket:'xxx'}
      type: Object,
    },
    // createOSS: {//是否在初始化时创建OSS实例
    //   type: Boolean,
    //   default: false
    // },
    imgWidth: {//图片宽度
      type: String,
      default: '196'
    },
    imgHeight: {//图片高度
      type: String,
      default: '146'
    },
    fileName: {//文件上传名-在阿里云的目录位置
      type: String,
    },
    uploadHeaders: {//文件上传携带头部
      type: Object,
    },
    videoPreview: {//是否开启视频预览
      type: Boolean,
      default: false
    },
    cancelUpload: {//是否开启取消上传功能
      type: Boolean,
      default: false
    },
    showProgress: {//是否显示上传视频的进度条
      type: Boolean,
      default: false
    },
    ossSign: {//此次的上传的辨别标识
      type: String,
      default: ''
    }

  },
  data () {
    return {
      client: [],//OSS 上传图片实例(用于解析)
      showUrl: '',//图片/视频地址
      dialogVisible: false,//视频预览弹窗
      uploadProgress: null,//视频上传进度
    }
  },

  watch: {
    showFileUrl (newVal) {
      this.showUrl = newVal
    },
    configureOSS (newVal) {
      if (this.configureOSS) {
        // 创建oss实例:可用来解析图片或视频
        this.client = new OSS(newVal)
        this.showUrl = this.showFileUrl
      } else {
        this.$message.error('缺少OSS实例创建配置参数,请使用configureOSS传入配置参数');
      }
    }
  },
  computed: {
    // 解析出图片/视频的阿里云访问链接
    OSSUrl () {
      return function (object) {
        if (this.client !== null) {
          // console.log(client.signatureUrl(object))
        }
        return this.client === null || !object || object.length === 0
          ? ''
          : this.client.signatureUrl(object, { expires: 3600 * 12 })
      }
    },

  },
  methods: {
    getVal () {
      return clientArr
    },
    // 停止上传
    stopUpload () {
      console.log(this.ossSign, 99999);
      if (clientArr.length > 0) {

        let index = clientArr.findIndex(item => (item.id == this.ossSign && item.client != null));

        if (clientArr[index].client) {
          this.$emit('uploadSuccess', 'stop')
          clientArr[index].client.cancel()
          clientArr[index].client = null
        }
      }
    },
    // 上传视频或图片
    async uploadImageOrVideo (file) {
      // 避免标识id同一时间上传多个视频
      if (clientArr.length > 0) {
        if (clientArr.some(item => (item.client != null && item.id == this.ossSign))) {
          return
        }

      }
      // 创建一个oss实例
      if (this.configureOSS) {
        if (this.fileName) {

          // 创建oss实例:可用来解析图片或视频
          let client = new OSS(this.configureOSS)
          clientArr.push({ id: this.ossSign, client: client })
          let index = clientArr.findIndex(item => (item.id == this.ossSign && item.client != null));

          this.$emit('createdOSS', 'create')
          // 获取上传的本地视频的时长
          var binaryData = [];
          // 传入file中raw
          binaryData.push(file.raw);
          //获取视频或者音频时长
          var fileurl = URL.createObjectURL(new Blob(binaryData));
          //经测试,发现audio也可获取视频的时长
          var audioElement = new Audio(fileurl);
          audioElement.addEventListener("loadedmetadata", function (_event) {
            //audioElement.duration就是视频时长
            file.duration = audioElement.duration.toFixed(0);
          });

          this.uploadProgress = 0
          const fileName = this.fileName + file.name.replace(/.+\./, '.')
          clientArr[index].client.multipartUpload(fileName, file.raw, {
            parallel: 4,
            // 设置分片大小。默认值为1 MB,最小值为100 KB。
            partSize: 1024 * 1024,
            meta: {
              year: new Date().getFullYear(),
              month: new Date().getMonth() + 1,
            },
            headers: this.uploadHeaders,
            // 上传进度回调
            progress: (percent, checkpoint) => {
              if (percent === 1) {
                this.uploadProgress = null
                clientArr[index].client = null
              } else {
                let resprogress = {
                  progress: Number((percent * 100).toFixed(2)),
                  ossSign: this.ossSign
                }
                this.$emit('uploadProgress', resprogress)
                this.uploadProgress = Number((percent * 100).toFixed(2))
              }
            }
          }).then(result => {
            let res = {
              duration: file.duration,
              url: result.name,
              ossSign: this.ossSign
            }
            this.$emit('uploadSuccess', res)
          }).catch(err => {
            if (err.name == 'cancel') {
              this.uploadProgress = null
            }
          })
        } else {
          this.$message.error('上传的文件名不能为空!');
        }
      } else {
        this.$message.error('缺少OSS实例创建配置参数,请使用configureOSS传入配置参数');
      }

    },
    // 
    uploadBefore () {
      this.$emit('uploadBefore', 'upload')
    }

  },
  created () {


  }
}
</script>

<style scoped>
.avatar-uploader {
  border: 1px dashed #d9d9d9;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  /* width: 196px;
  height: 146px;
  line-height: 178px; */
  text-align: center;
}
.avatar {
  /* width: 196px;
  height: 146px; */
  display: block;
}

.video-main {
  display: flex;
  align-items: center;
}
</style>

-Oss组件封装使用文档

  1. vscode启动项目后,安装ali-oss模块。然后在需要使用的文件中引入组件,注册并使用。(注:组件中有使用element ui,需要引用此组件的项目提供运行环境支持),示例:

  1. 使用组件。示例:

组件相关参数

  1. 方法

参数

说明

类型

默认值

必传

uploadType

上传的类型:image-图片,video-视频

String

image

showFileUrl

要显示的image/video在阿里云服务器上的地址

String

configureOSS

创建OSS实例所需的配置项: 示例:{region:'oss-cn-shenzhen',accessKeyId:'xxx',accessKeySecret:'xxx',stsToken:'xxx',timeout:'xxx',bucket:'xxx'}

Object

imgWidth

上传类型为image时,图片的宽度

String

196(仅传数值,固定px单位)

imgHeight

上传类型为image时,图片的高度

String

146(仅传数值,固定px单位)

fileName

文件上传名(在阿里云的目录地址)

String

uploadHeaders

文件上传是设置的头部请求(根据具体需求选择是否上传)

Object

videoPreview

是否开启视频预览

Boolean

false

cancelUpload

是否开启取消上传功能

Boolean

false

showProgress

是否显示上传视频的进度条

Boolean

false

ossSign

此次上传的标识(批量上传时用于辨别)

String

方法名

说明

备注

uploadSuccess

上传成功回调

uploadProgress

上传进度回调

同时使用多个组件时,数据可能会错乱。

uploadBefore

选择文件的触发事件

用于更新OSS示例参数

createdOSS

创建OSS实例时触发

用于监听创建的OSS数量

版本:1.0.0

说明:初始版本,后面会陆续补充和优化内容

实际应用中,发现短时间内可触发上传按钮两次,可能会创建出两个实例,因此补充获取组件创建上传实例的方法:getVal(),具体使用如下:

在调用组件的父级页面:

然后获取子组件的创建实例情况:

注:上传视频完成会销毁对应的OSS实例,所以client不为空的及存在实例数。

版本:1.0.1

说明:优化了OSS实例创建规则,增加了OSS实例数获取方式

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值