vue+elementui运用el-upload结合vod-js-sdk-v6实现腾讯云点播视频上传

第一步:npm install vod-js-sdk-v6

写成组件 upload代码片

// An highlighted block
<template>
  <div style="width: 400px">
    <el-upload
      action="#"
      :accept="accept"
      :disabled="disabled"
      :limit="1"
      :http-request="uploadVideo"
      :before-upload="beforeUploadVideo"
      :on-exceed="handleExceed"
      :show-file-list="false"
    >
      <el-button :disabled="disabled" :loading="loading" class="button-uploader" size="small" type="primary">
        <i class="fa fa-upload" />
        上传视频/音频
      </el-button>
    </el-upload>
    <el-progress v-if="loading" :percentage="progress" />
  </div>
</template>

<script>
import { getSignature, getAntiLeechUrl } from '@/api/upload.js'
import { sendVideoResource } from '@/api/learning'
import moment from 'moment'
import TcVod from 'vod-js-sdk-v6'
export default {
  name: 'UploadVideo',
  props: {
    accept: {
      type: String,
      default: 'video/mp4, audio/mp3'
    },
    title: {
      type: String,
      default: ''
    },
    disabled: {
      type: Boolean,
      default: false
    },
    watermarkFlag: {
      type: String,
      default: '1'
    },
    classId: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      resourceType: '',
      videoDuration: 1000,
      uploaderInfo: {},
      progress: 0,
      percentageImage: 0,
      loading: false
    }
  },
  created() {
  },
  methods: {
    // 视频处理
    handleExceed(files, fileList) {
      this.$message.error(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
    },
    beforeUploadVideo(file) {
      if (this.title === '') {
        this.popMessage('视频上传前,请先填写课程标题')
        return false
      }
      if (this.classId === '') {
        this.popMessage('视频上传前,请先选择科目并确定是否添加水印')
        return false
      }
      if (['video/mp4', 'audio/mp3'].indexOf(file.type) === -1) {
        this.popMessage('请上传正确的音频或视频格式')
        return false
      }
      if (file.type === 'video/mp4') {
        const isLt1G = file.size / 1024 / 1024 < 1024
        if (!isLt1G) {
          this.popMessage('上传视频大小不能超过1G')
          return false
        }
        this.resourceType = '1'
      }
      if (file.type === 'audio/mp3') {
        const isLt100M = file.size / 1024 / 1024 < 100
        if (!isLt100M) {
          this.popMessage('上传音频大小不能超过100M')
          return false
        }
        this.resourceType = '2'
      }
    },
    popMessage(message) {
      this.$message.error(message)
      this.loading = false
    },
    uploadVideo(event) {
      this.loading = true
      this.start(event.file)
    },
    // 自定义上传
    async start(file) {
      try {
        // eslint-disable-next-line no-irregular-whitespace
        const userName = this.$store.getters.name
        const currentTime = moment(Date.now()).format('YYYYMMDDHHmmss')
        const type = file.type.split('/')[1]
        const copyFile = new File([file], `${this.title}_${currentTime}.${type}`)
        const _this = this
        const tcVod = new TcVod({ getSignature: this.getSignature })
        // 视频,类型为 File
        const uploader = tcVod.upload({
          mediaFile: copyFile
        })
        // 视频上传进度
        uploader.on('media_progress', info => {
          this.progress = parseInt(info.percent * 100)
          uploaderInfo.progress = parseInt(info.percent * 100)
        })
        // 视频上传完成
        uploader.on('media_upload', function(info) {
          uploaderInfo.isVideoUploadSuccess = true
        })
        var uploaderInfo = {
          videoInfo: uploader.videoInfo,
          coverInfo: uploader.coverInfo,
          isVideoUploadSuccess: false,
          isVideoUploadCancel: false,
          isCoverUploadSuccess: false,
          resourceType: _this.resourceType,
          progress: 0,
          coverProgress: 0,
          fileId: '',
          videoUrl: '',
          coverUrl: '',
          cancel: function() {
            uploaderInfo.isVideoUploadCancel = true
            uploader.cancel()
          }
        }
        this.uploaderInfo = uploaderInfo
        uploader.done().then(function(doneResult) {
          uploaderInfo.fileId = doneResult.fileId
          if (uploaderInfo.isVideoUploadSuccess) {
            _this.sendVideoResource(doneResult.fileId, doneResult.video.url, userName)
          }
          return _this.getAntiLeechUrl(doneResult.video.url, _this.videoDuration)
        }).then(function(videoUrl) {
          uploaderInfo.videoUrl = videoUrl
          _this.$emit('subUploadSucceed', uploaderInfo)
          _this.loading = false
        })
      } catch (error) {
        this.loading = false
        this.$emit('subUploadSucceed', '')
      }
    },
    async getSignature() {
      const params = {
        resourceType: this.resourceType,
        watermarkFlag: Number(this.watermarkFlag),
        classId: this.classId
      }
      const res = await getSignature(params)
      if (res.code === 0) {
        return res.data
      } else this.$message({ message: res.msg, type: 'error' })
    },
    async getAntiLeechUrl(url, duration) {
      const query = {
        originalUrl: url,
        duration: duration
      }
      const res = await getAntiLeechUrl(query)
      if (res.code === 0) {
        this.videoUrl = res.data
        return res.data
      } else this.$message({ message: res.msg, type: 'error' })
    },
    async sendVideoResource(fileId, url, userName) {
      const query = {
        fileId: fileId,
        mediaUrl: url,
        createdBy: userName
      }
      const res = await sendVideoResource(query)
      if (res.code === 0) {
        return res.data
      } else this.$message({ message: res.msg, type: 'error' })
    }
  }
}
</script>

<style lang="scss" scoped>
.clear-margin-top {
  margin-top: 0;
}
.button-uploader {
  background: #EEF5FF;
  border: 1px solid #CFE3FD;
  color: #5E9FF8;
}
</style>

父组件接收

下面展示一些 内联代码片

// An highlighted block
<template>
      <el-form-item label="课件" required>
        <div class="tip">视频大小不超过1G,格式为mp4;音频大小不超过100M,格式为mp3</div>
        <UploadVideo
          :title="formData.title"
          :watermark-flag="formData.watermarkFlag"
          :class-id="String(formData.subject)"
          :disabled="formData.packageFlag"
          @subUploadSucceed="getVideoUploadSucceedResult"
        />
        <video v-if="videoUrl && resourceType === '1'" controls="controls" class="avatar" :src="videoUrl" />
        <audio
          v-if="videoUrl && resourceType === '2'"
          controls="controls"
          :src="videoUrl"
          :style="{ height: '74px'}"
        />
        <div v-if="isUploadFailed" style="color: red">上传失败,请重新上传</div>
      </el-form-item>
</template>
<scirpt>
export default {
  methods: {
    getVideoUploadSucceedResult(uploaderInfo) {
      if (uploaderInfo !== '') {
        this.videoUrl = uploaderInfo.videoUrl
        this.resourceType = uploaderInfo.resourceType
        this.formData.fileId = uploaderInfo.fileId
      } else {
        this.isUploadFailed = true
      }
    }
  }
}
</script>

更新版本

<template>
  <div style="width: 400px;">
    <el-upload
      ref="media"
      action="#"
      :disabled="disabled"
      :accept="accept"
      :http-request="uploadVideo"
      :before-upload="beforeUploadVideo"
      :on-exceed="handleExceed"
      :limit="1"
      :show-file-list="false"
    >
      <el-button :disabled="disabled" :loading="loading" plain size="mini" type="primary">
        <i class="fa fa-upload" />
        上传视频/音频
      </el-button>
    </el-upload>

    <el-row style="margin-top: 10px">
      <span v-if="fileName" style="margin: 10px;color: #606266;"> {{ fileName }} </span>
      <div v-if="videoUrl && resourceType === '1'" class="video">
        <video controls="controls" class="avatar-video" :src="videoUrl" />
        <i v-if="videoUrl && !disabled" class="el-icon-close close" @click="removeMedia" />
      </div>
      <div v-if="videoUrl && resourceType === '2' && showAudio" class="audio">
        <audio controls="controls" class="avatar-audio" :src="videoUrl" />
        <i v-if="videoUrl && !disabled" class="el-icon-close close" @click="removeMedia" />
      </div>
    </el-row>

    <div v-if="isUploadFailed" style="color: red">上传失败,请重新上传</div>

    <el-row type="flex" class="progress">
      <el-progress v-if="loading" :percentage="progress" />
      <i v-if="loading" class="el-icon-close" @click="cancelUpload" />
    </el-row>
  </div>
</template>

<script>
import { getSignature, getAntiLeechUrl } from '@/api/upload.js'
import { sendVideoResource } from '@/api/learning'
import moment from 'moment'
import TcVod from 'vod-js-sdk-v6'
export default {
  name: 'UploadMediaVideo',
  props: {
    accept: {
      type: String,
      default: '.mp4, .mp3, .vob, .mpg'
    },
    disabled: {
      type: Boolean,
      default: false
    },
    watermarkFlag: {
      type: Boolean,
      default: true
    },
    classId: {
      type: String,
      default: ''
    },
    mediaType: {
      type: Number,
      default: 1
    },
    showAudio: {
      type: Boolean,
      default: true
    },
    mediaContent: {
      type: Object,
      default: null
    }
  },
  data() {
    return {
      resourceType: '',
      videoDuration: 1000,
      uploaderInfo: {},
      progress: 0,
      percentageImage: 0,
      loading: false,
      isUploadFailed: false,
      videoUrl: '', // 图片路径
      fileId: '', // 视频id
      fileName: '' // 音视频名称
    }
  },
  watch: {
    mediaContent(val) {
      this.videoUrl = val.mediaUrl
      this.resourceType = String(val.mediaType)
      this.fileName = val.fileName
    },
    showAudio(val) {
      if (!val) {
        this.fileId = ''
        this.fileName = ''
        this.progress = 0
        this.loading = false
        this.$refs.media.clearFiles()
        this.$emit('setTitle', this.fileName)
      }
    }
  },
  methods: {
    // 视频处理
    handleExceed(files, fileList) {
      this.$message.error(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
    },
    beforeUploadVideo(file) {
      if (!this.classId) {
        this.popMessage('音视频上传前,请先选择云存储路径和水印')
        return false
      }
      const startLength = Number(file.name.lastIndexOf('.')) + 1
      const type = file.name.substr(startLength).toLowerCase()
      if (this.mediaType === 1) {
        if (type === 'mp4' || type === 'mpg' || type === 'vob') {
          const isLt2G = file.size / 1024 / 1024 < 2048
          if (!isLt2G) {
            this.popMessage('上传视频大小不能超过2G')
            return false
          }
          this.resourceType = '1'
        } else {
          this.popMessage('请上传视频类型文件')
          return false
        }
      }
      if (this.mediaType === 2) {
        if (type === 'mp3') {
          const isLt100M = file.size / 1024 / 1024 < 100
          if (!isLt100M) {
            this.popMessage('上传音频大小不能超过100M')
            return false
          }
          this.resourceType = '2'
        } else {
          this.popMessage('请上传音频类型文件')
          return false
        }
      }
    },
    popMessage(message) {
      this.$message.error(message)
      this.loading = false
    },
    uploadVideo(event) {
      this.loading = true
      this.start(event.file)
    },
    // 自定义上传
    async start(file) {
      try {
        // eslint-disable-next-line no-irregular-whitespace
        const userName = this.$store.getters.name
        const currentTime = moment(Date.now()).format('YYYYMMDDHHmmss')
        const startLength = Number(file.name.lastIndexOf('.'))
        const type = file.name.substr(startLength).toLowerCase()
        const title = file.name.substr(0, startLength)
        const copyFile = new File([file], `${title}_${currentTime}${type}`)
        const _this = this
        _this.fileName = file.name
        _this.$emit('setTitle', _this.fileName)
        const tcVod = new TcVod({ getSignature: this.getSignature })
        // 视频,类型为 File
        const uploader = tcVod.upload({
          mediaFile: copyFile
        })
        // 视频上传进度
        uploader.on('media_progress', info => {
          this.progress = parseInt(info.percent * 100)
          uploaderInfo.progress = parseInt(info.percent * 100)
        })
        // 视频上传完成
        uploader.on('media_upload', function(info) {
          uploaderInfo.isVideoUploadSuccess = true
        })
        var uploaderInfo = {
          videoInfo: uploader.videoInfo,
          coverInfo: uploader.coverInfo,
          isVideoUploadSuccess: false,
          isVideoUploadCancel: false,
          isCoverUploadSuccess: false,
          resourceType: _this.resourceType,
          progress: 0,
          coverProgress: 0,
          fileId: '',
          videoUrl: '',
          coverUrl: '',
          cancel: function() {
            uploaderInfo.isVideoUploadCancel = true
            uploader.cancel()
          }
        }
        this.uploaderInfo = uploaderInfo
        uploader.done().then(function(doneResult) {
          _this.fileId = doneResult.fileId
          if (uploaderInfo.isVideoUploadSuccess) {
            _this.sendVideoResource(doneResult.fileId, doneResult.video.url, userName)
          }
          return _this.getAntiLeechUrl(doneResult.video.url, _this.videoDuration)
        }).then(function(videoUrl) {
          const content = {
            fileId: _this.fileId,
            fileName: _this.fileName
          }
          _this.$emit('subUploadSucceed', content)
          _this.isUploadFailed = false
          _this.loading = false
        })
      } catch (error) {
        this.fileName = ''
        this.loading = false
        this.isUploadFailed = true
      }
    },
    cancelUpload() {
      if (this.uploaderInfo.progress !== 0) {
        this.uploaderInfo.cancel()
      }
      this.fileName = ''
      this.progress = 0
      this.loading = false
      this.$refs.media.clearFiles()
      this.$emit('setTitle', this.fileName)
    },
    removeMedia() {
      this.uploaderInfo = {}
      this.videoUrl = ''
      this.fileId = ''
      this.fileName = ''
      this.progress = 0
      this.$refs.media.clearFiles()
      const content = {
        fileId: this.fileId,
        fileName: this.fileName
      }
      this.$emit('subUploadSucceed', content)
    },
    async getSignature() {
      const params = {
        resourceType: this.resourceType,
        watermarkFlag: this.watermarkFlag,
        classId: this.classId
      }
      const res = await getSignature(params)
      if (res.code === 0) {
        return res.data
      } else this.$message({ message: res.msg, type: 'error' })
    },
    async getAntiLeechUrl(url, duration) {
      const query = {
        originalUrl: url,
        duration: duration
      }
      const res = await getAntiLeechUrl(query)
      if (res.code === 0) {
        this.videoUrl = res.data
        return res.data
      } else this.$message({ message: res.msg, type: 'error' })
    },
    async sendVideoResource(fileId, url, userName) {
      const query = {
        fileId: fileId,
        mediaUrl: url,
        createdBy: userName
      }
      const res = await sendVideoResource(query)
      if (res.code === 0) {
        return res.data
      } else this.$message({ message: res.msg, type: 'error' })
    }
  }
}
</script>

<style lang="scss" scoped>
.clear-margin-top {
  margin-top: 0;
}
.progress {
  .el-progress {
    width: 90%;
  }

  i {
    color: #FF0000;
    border-radius: 50%;
    background-color: #F9F9F9;
  }

  i:hover {
    background: #FF0000;
    color: #FFFFFF;
  }
}

.video {
  display: flex;
  width: 178px;
  position: relative;

  .avatar-video {
    width: 100%;
    height: 178px;
    display: block;
  }

  .close {
    position: absolute;
    top: 4px;
    right: 4px;
    background: rgba(255, 255, 255, 1);
    border-radius: 50%;
    font-weight: 600;
  }

  i {
    height: 15px;
    color: #FF0000;
    border-radius: 50%;
    background-color: #F9F9F9;
  }

  i:hover {
    background: #FF0000;
    color: #FFFFFF;
  }
}

.audio {
  display: flex;
  width: 360px;
  position: relative;

  .avatar-audio {
    width: 100%;
    margin-top: 10px;
    display: block;
  }

  .close {
    position: absolute;
    top: 4px;
    right: 4px;
    background: rgba(255, 255, 255, 1);
    border-radius: 50%;
    font-weight: 600;
  }

  i {
    height: 15px;
    color: #FF0000;
    border-radius: 50%;
    background-color: #F9F9F9;
  }

  i:hover {
    background: #FF0000;
    color: #FFFFFF;
  }
}
</style>

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页