vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > vue与axios上传视频并显示上传进度

vue与axios上传视频并显示上传进度情况

作者:little_shallot

本文讲述了项目中实现上传视频并显示上传进度的功能,首先使用axios库进行单文件引入,未进行封装,通过element组件库实现选择文件上传,并打印选择文件的信息,上传完成后,可以在展示区域显示上传的视频,鼠标移入播放区域时会有相应的效果

做项目难免会有各种各样的需求,这次是上传视频并显示上传进度,好的我们开始吧

首先引入axios

我这里是单文件引入,没有使用封装

import axios from 'axios'

主要用到的参数有

      exception: '-', //进度条当前状态
      videolist: [], // 视频合集
      progress: 0, // 进度条
      video: '',  //保存预留地址

需要个触发选择文件上传的按钮

这里用的element做为布局

   <el-form-item label="视频">
        <div>
        	//限制上传完成才能上传下一个
          <label v-if="progress === 0" class="btn" for="uploadvideo">上传视频</label>
          <label v-else class="btn" @click="uploading">上传视频</label>
          <input
            id="uploadvideo"
            style="display:none;"
            type="file"
            accept="video/*"
            @change="selectvideo($event)"
          >
        </div>
      </el-form-item>

  // 未上传完成阻止
    uploading() {
      this.$message({
        message: '请等待上传完成',
        type: 'error'
      })
    },

accept(选择的文件格式),点击上传之后选择文件会触发事件回调,打印如下:

拿到之后就可以上传到服务器了

 // 上传视频
    selectvideo(e) {
      this.exception = '-'
      const file = e.target.files[0] // 获取选中的文件
      if ([
        'video/mp4',
        'video/ogg',
        'video/flv',
        'video/avi',
        'video/wmv',
        'video/rmvb',
        'video/mov'
      ].indexOf(file.type) === -1
      ) {
        // layer.msg('请上传正确的视频格式')
        return false
      }
      if (!file.size) {
        // layer.msg('视频大小不能超过50MB')
        return false
      }
      const reader = new FileReader()
      reader.onload = e => {
        let data
        if (typeof e.target.result === 'object') {
          data = window.URL.createObjectURL(new Blob([e.target.result]))
        } else {
          data = e.target.result
        }
        this.videosrc = data
        // 获取转换后的地址地址
      }
      // 转化为base64
      reader.readAsDataURL(file)
      const formData = new FormData() // 创建form对象
      formData.append('file', file) // 通过append向form对象添加数据const res = await upLoadImage(formData);
      axios({
        url: this.apiUrl + '/file',
        method: 'post',
        data: formData,
        headers: { 'Content-Type': 'multipart/form-data', Authorization: `${this.uploadHeaders.Authorization}` },
        // 原生获取上传进度的事件
        onUploadProgress: progressEvent => {
          const process = ((progressEvent.loaded / progressEvent.total) * 100) | 0
          this.progress = process
        }
      }).then(res => {
        this.$message({ message: `上传${res.data.msg}`, type: 'success' })
        // 进度条变成成功状态
        this.exception = 'success'
        // 延时初始化进度条
        setTimeout(() => {
          this.progress = 0
          // 数据填充 获取本地转化为base64的地址和上传成功地址
          this.videolist.push({ data: this.videosrc, src: this.apiUrl + '/file/getImgStream?idFile=' + res.data.data.realFileName })
        }, 500)
      }).catch(_error => {
        this.$message({ message: `上传失败`, type: 'error' })
        // 进度条变成失败状态
        this.exception = 'exception'
        // 延时初始化进度条
        setTimeout(() => { this.progress = 0 }, 2000)
      })
      //   防止第二次同一个文件不能选中
      e.target.value = ''
    },

然后上传完成之后就是展示区域

 <el-form-item>
        <div class="list-image">
          <div v-for="(item,index) in videolist" :key="index">
            <video class="video" :src="item.data" alt="" />
            <span><i class="el-icon-delete" @click="deletevideo(index)" /><i
              class="el-icon-caret-right"
              style="font-size: 23px;margin-left: 5px;"
              @click="pay(index)"
            /></span>
          </div>
          <el-progress
            v-if="progress"
            type="circle"
            :percentage="progress"
            style="height: 126px; width: 126px;"
            :status="exception"
          />
        </div>
      </el-form-item>

中间好像不显示,可以自行修改

遮罩样式

.list-image {
  width: 600px;
  display: flex;
  flex-wrap: wrap;
  div,
  .videolist {
    width: 150px;
    height: 150px;
    display: inline-block;
    position: relative;
    margin-right: 30px;
    margin-bottom: 30px;
    border-radius: 6px;
    overflow: hidden;
    transition: opacity 0.3s;
    img,
    video {
      width: 100%;
      height: 100%;
    }
    span {
      position: absolute;
      width: 100%;
      height: 100%;
      left: 0;
      top: 0;
      cursor: default;
      text-align: center;
      color: #fff;
      opacity: 0;
      font-size: 20px;
      background-color: rgba(0, 0, 0, 0.5);
      transition: opacity 0.3s;
      display: flex;
      align-items: center;
      justify-content: center;
      i:hover {
        cursor: pointer;
      }
    }
  }
  div:hover span {
    opacity: 1;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.5);
  }
}

鼠标移上去的事件

    // 删除
    deletevideo(e) {
      this.videolist.splice(e, 1)
      this.video = ''
    },
    // 播放
    pay(index) {
      this.video = this.videolist[index].data
      this.dialogTableVisible = true
    },
    // 弹窗消失清空地址
    close() {
      this.dialogTableVisible = false
      this.video = ''
    }

播放区域

   <el-dialog :visible.sync="dialogTableVisible" style="text-align: center" :before-close="close">
        <video :src="video" controls="controls" autoplay width="500px" />
      </el-dialog>

效果:

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文