vue vantUI实现文件(图片、文档、视频、音频)上传(多文件)


Posted in Javascript onOctober 15, 2019

说在前面

网上有很多种文件上传的方法,根据公司最近的业务需求,要求实现多种文件的上传,在实现过程中,查阅了很多资料,最后,终于把功能实现了,开心!

<template>
  <div>
    <v-header :left-text="`上传${columnName}`"></v-header>

    <div class="upload">
      <div v-if="columnName === '视频'">
        <div class="forPreview_video" v-for="(item, index) in uploadVideoList" :key="index">
          <video :src="videoSrc"></video>
          <van-icon name="delete" @click="delBtn(index)" class="delte"/>
        </div>
        <van-uploader v-show="uploadVideoList.length < 2" preview-size="80px" accept="video/*" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
      </div>

      <div v-if="columnName === '文档'">
        <div class="forPreview_doc" v-for="(item, index) in uploadDocList" :key="index">
          <img src="../../assets/img/resource_doc_b@2x.png" alt="">
          <span>{{item.name}}</span>
          <span>{{item.size | formatSize}}</span>
          <van-icon name="delete" @click="delBtn(index)" class="delte"/>
        </div>
        <van-uploader v-show="uploadDocList.length < 2" preview-size="80px" accept=".doc, .docx, .xml, .xlsx, .pdf" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
      </div>

      <div v-if="columnName === '音频'">
        <div class="forPreview_audio" v-for="(item, index) in uploadAudioList" :key="index">
          <img src="../../assets/img/resource_audio@2x.png" alt="">
          <span>{{item.name}}</span>
          <span>{{item.size | formatSize}}</span>
          <van-icon name="delete" @click="delBtn(index)" class="delte"/>
        </div>
        <van-uploader v-show="uploadAudioList.length < 2" preview-size="80px" accept="audio/*" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
      </div>

      <div v-if="columnName === '图片'">
        <div class="forPreview_pic" v-for="(item, index) in uploadPicList" :key="index">
          <img :src="picSrc" alt="">
          <van-icon name="delete" @click="delBtn(index)" class="delte"/>
        </div>
        <van-uploader v-show="uploadPicList.length < 2" accept="image/*" preview-size="80px" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
      </div>

      <div class="diy-submit">
        <van-button @click="doSubmit($event)">提交</van-button>
      </div>
    </div>
  </div>
</template>

上述html代码是在同一页面根据前一页面传回的columnName的值来判断需要上传哪种类型文件。

<script>
  import VHeader from '../../common/header'
  import {classifyList, uploadFile, addResources} from '../../http/mock'
  import Toast from 'vant'
  export default {
    name: "uploadFile",
    components: {
      VHeader
    },
    data(){
      return{
        tagList: [], 
        uploadTitle: '',
        currentTag: null,
        tagId: null,
        columnName: localStorage.getItem('columnName'),
        fileIdArr: [],

        uploadVideoList: [], // 选中的上传视频列表
        videoSrc: '',  // 选中的视频的src,用来显示视频
        uploadDocList: [], // 选中的上传文档列表
        uploadAudioList: [], // 选中的上传音频列表
        uploadPicList: [], // 选中的上传图片列表
        picSrc: '', // 选中的图片的src,用来显示图片缩略图
      }
    },
    filters: {
      formatSize(val) { // 格式化文件大小
        if (val > 0) {
          return (val / 1024 / 1024).toFixed(2) + 'M';
        } else {
          return '0M';
        }
      },
    },
    methods: {
      // vant上传文件前校验文件事件
      // 文件选中后先提交给后台,后台根据选中的文件,返回数组(这一业务根据后台而定)
      beforeRead(file){
        let formData = new FormData(); // 为上传文件定义一个formData对象
        let config = {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        };
        let uploadUrl = URL.createObjectURL(file); // 将选中的上传文件转化为二进制文件,显示在页面上
        if(this.columnName === '视频'){
          this.uploadVideoList.push(file);
          this.videoSrc = uploadUrl;
          // 这里使用foreach是为了将选中的多个文件都添加进定义的formdata变量中
          this.uploadVideoList.forEach(item => {
            formData.append(item.name, item)
          })
        }else if(this.columnName === '文档'){
          this.uploadDocList.push(file);
          this.uploadDocList.forEach(item => {
            formData.append(item.name, item)
          })
        }else if(this.columnName === '音频'){
          this.uploadAudioList.push(file);
          this.uploadAudioList.forEach(item => {
            formData.append(item.name, item)
          })
        }else if(this.columnName === '图片'){
          this.uploadPicList.push(file);
          this.picSrc = uploadUrl;
          this.uploadPicList.forEach(item => {
            formData.append(item.name, item)
          })
        }


        // formData.append(file.name, file); // 单个文件上传时可以这么写,上面的foreach就可以删掉
        this.$api.post(uploadFile, formData, config).then(res => {
          this.fileIdArr = res.data.data;  // 把?中的文件?魉徒o後台
        }).catch(err => {
          Toast('文件上?魇?。?)
        })
      },
      // 删除待上传的文件
      delBtn(index){
        if(this.columnName === '视频'){
          // 先判断当前的选中的索引是否是在有效范围中,如果不是则跳出方法 
          if(isNaN(index) || index >= this.uploadVideoList.length){
            return false;
          }
          let tmp = [];
          // 将没被选中的上传文件存放进一个临时数组中
          for(let i = 0; i < this.uploadVideoList.length; i++){
            if(this.uploadVideoList[i] !== this.uploadVideoList[index]){
              tmp.push(this.uploadVideoList[i]);
            }
          }
          // 存放当前未被选中的上传文件
          this.uploadVideoList = tmp;
        }

        if(this.columnName === '文档'){
          console.log(this.uploadDocList.length)
          if(isNaN(index) || index >= this.uploadDocList.length){
            return false;
          }
          let tmp = [];
          for(let i = 0; i < this.uploadDocList.length; i++){
            if(this.uploadDocList[i] !== this.uploadDocList[index]){
              tmp.push(this.uploadDocList[i]);
            }
          }
          this.uploadDocList = tmp;
        }

        if(this.columnName === '音频'){
          if(isNaN(index) || index >= this.uploadAudioList.length){
            return false;
          }
          let tmp = [];
          for(let i = 0; i < this.uploadAudioList.length; i++){
            if(this.uploadAudioList[i] !== this.uploadAudioList[index]){
              tmp.push(this.uploadAudioList[i]);
            }
          }
          this.uploadAudioList = tmp;
        }

        if(this.columnName === '图片'){
          if(isNaN(index) || index >= this.uploadPicList.length){
            return false;
          }
          console.log('uuu')
          let tmp = [];
          for(let i = 0; i < this.uploadPicList.length; i++){
            if(this.uploadPicList[i] !== this.uploadPicList[index]){
              tmp.push(this.uploadPicList[i]);
            }
          }
          this.uploadPicList = tmp;
        }
      },
      doSubmit(){
        let params = {
          classify: this.tagId,    // 针对视频资源时对应的分类id
          file: this.fileIdArr,  // 选择完文件后,调用uploadFile这个接口,后端返回的数组
          resourceColumnId: JSON.parse(localStorage.getItem('columnId')),  // 资源栏目id(视频、图片、音频、文档)
          title: this.uploadTitle  // 上传时填写的标题
        };
        let columnName = localStorage.getItem('columnName')
        this.$api.post(addResources, params).then(res => {
          if(res.data.code === 1001){
            if(columnName === '视频'){
              this.$router.push({name: 'myVideo'});
            }else {
              this.$router.push({name: 'myResourceClassify'});
            }
          }
        }).catch(err => {
          console.log(err)
        })
      },
    },
    mounted(){
      this.getClassifyList();
    }
  }
</script>
<style lang="less" scoped>
  .upload{
    padding: 140px 36px 160px 36px;
    box-sizing: border-box;
  }

  .forPreview_video{
    position: relative;
    /*background: rgba(0,0,0,.7);*/
    video{
      width: 95%;
      max-height: 430px;
    }
    .delte{
      position: absolute;
      right: 0;
      bottom: 0;
    }
  }
  .forPreview_doc, .forPreview_audio{
    display: flex;
    margin-bottom: 10px;
    align-items: center;
    img{
      width: 56px;
      height: 56px;
      margin-right: 20px;
    }
    span:nth-of-type(1){
      flex: 1;
    }
    span:nth-of-type(2){
      margin-right: 20px;
    }
  }
  .forPreview_pic{
    display: flex;
    align-items: flex-end;
    img{
      width: 160px;
      height: 160px;
    }
  }

  .diy-detail{
    width: 100%;
    overflow: hidden;
    
    .btn{
      span{
        margin-bottom: 10px;
      }
    }
    .van-cell{
      background-color: #F0F0F0;
      border-radius: 35px;
      font-size: 26px;
      height: 69px;
      line-height: 69px;
      padding: 0 22px;
      color: #999;
    }
    .van-hairline--top-bottom::after, .van-hairline-unset--top-bottom::after {
      border-width: 0;
    }
    p{
      height: 64px;
      line-height: 64px;
      font-size: 32px;
      color: #333;
      position: relative;
      padding-left: 16px;
    }
    p::before{
      position: absolute;
      top: 0;
      left: 0;
      content: '*';
      color: #FF0000;
    }

    span{
      display: inline-block;
      width: 157px;
      background: #F0F0F0;
      border-radius: 35px;
      color: #999;
      font-size: 26px;
      padding: 14px 18px;
      margin-right: 28px;
      text-align: center;
    }
    .active{
      color: #fff;
      background: linear-gradient(to right,#FD5130,#FA6C34);
    }
  }
  .diy-submit {
    position: fixed;
    height: 150px;
    width: 90%;
    bottom: 0;
    background: #fff;

    .van-button {
      width: 100%;
      height: 90px;
      border-radius: 45px;
      font-size: 36px;
      color: #fff;
      background: linear-gradient(to right, #FD5130, #FA6C34);
      top: 50%;
      transform: translate(0, -50%);
    }
    .van-button--default {
      border: none;
    }
  }
</style>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
关于jQuery新的事件绑定机制on()的使用技巧
Apr 26 Javascript
使用ImageMagick进行图片缩放、合成与裁剪(js+python)
Sep 16 Javascript
读取input:file的路径并显示本地图片的方法
Sep 23 Javascript
浏览器的JavaScript引擎的识别方法
Oct 20 Javascript
javascript实现行拖动的方法
May 27 Javascript
jQuery实现Email邮箱地址自动补全功能代码
Nov 03 Javascript
浅谈javascript中onbeforeunload与onunload事件
Dec 10 Javascript
jQuery实现的简单分页示例
Jun 01 Javascript
微信小程序教程系列之设置标题栏和导航栏(7)
Jun 29 Javascript
AngularJS对动态增加的DOM实现ng-keyup事件示例
Mar 12 Javascript
JavaScript实现创建自定义对象的常用方式总结
Jul 09 Javascript
JavaScript 声明私有变量的两种方式
Feb 05 Javascript
ES6中let、const的区别及变量的解构赋值操作方法实例分析
Oct 15 #Javascript
vue使用@scroll监听滚动事件时,@scroll无效问题的解决方法详解
Oct 15 #Javascript
vue实现树形结构样式和功能的实例代码
Oct 15 #Javascript
谈谈IntersectionObserver懒加载的具体使用
Oct 15 #Javascript
js实现开关灯效果
Mar 30 #Javascript
JS实现灯泡开关特效
Mar 30 #Javascript
浅谈微信小程序列表埋点曝光指南
Oct 15 #Javascript
You might like
解析curl提交GET,POST,Cookie的简单方法
2013/06/29 PHP
Yii操作数据库的3种方法
2014/03/11 PHP
PHP实现电商订单自动确认收货redis队列
2017/05/17 PHP
php实现表单提交上传文件功能
2018/05/28 PHP
Thinkphp5+Redis实现商品秒杀代码实例讲解
2020/12/29 PHP
javascript时间自动刷新实现原理与步骤
2013/01/06 Javascript
jQuery根据纬度经度查看地图处理程序
2013/05/08 Javascript
PHP+jQuery实现随意拖动层并即时保存拖动位置
2015/04/30 Javascript
JQuery+Ajax实现数据查询、排序和分页功能
2015/09/27 Javascript
javascript实现的网站访问量统计代码
2015/12/20 Javascript
JS及PHP代码编写八大排序算法
2016/07/12 Javascript
Javascript Function.prototype.bind详细分析
2016/12/29 Javascript
为什么我们要做三份 Webpack 配置文件
2017/09/18 Javascript
ES6中let 和 const 的新特性
2018/09/03 Javascript
JS中的算法与数据结构之队列(Queue)实例详解
2019/08/20 Javascript
js实现树形数据转成扁平数据的方法示例
2020/02/27 Javascript
JavaScript计算出两个数的差值
2020/03/19 Javascript
[01:19]2014DOTA2国际邀请赛 采访TITAN战队ohaiyo 能赢DK很幸运
2014/07/12 DOTA
[51:06]DOTA2-DPC中国联赛 正赛 Elephant vs Aster BO3 第二场 1月26日
2021/03/11 DOTA
寻找网站后台地址的python脚本
2014/09/01 Python
详解Python中DOM方法的动态性
2015/04/11 Python
Python3网络爬虫之使用User Agent和代理IP隐藏身份
2017/11/23 Python
在cmd命令行里进入和退出Python程序的方法
2018/05/12 Python
python leetcode 字符串相乘实例详解
2018/09/03 Python
详解python中docx库的安装过程
2019/11/08 Python
浅谈pandas dataframe对除数是零的处理
2020/07/20 Python
python 获取域名到期时间的方法步骤
2021/02/10 Python
详解如何将 Canvas 绘制过程转为视频
2021/01/25 HTML / CSS
德国PC硬件网站:CASEKING
2016/10/20 全球购物
Tech21美国/加拿大:英国NO.1防摔保护壳品牌
2018/01/20 全球购物
日本动漫周边服饰销售网站:Atsuko
2019/12/16 全球购物
写clone()方法时,通常都有一行代码,是什么?
2012/10/31 面试题
婚假请假条怎么写
2014/04/10 职场文书
汉语专业毕业生自荐信
2014/07/06 职场文书
学校党员干部承诺书
2015/05/04 职场文书
redis击穿 雪崩 穿透超详细解决方案梳理
2022/03/17 Redis