vue结合WebUploader插件实现大文件分片上传

1.下载webuploader

下载地址:官网http://fex.baidu.com/webuploader/
在这里插入图片描述

2.引入webuploader

使用Web Uploader文件上传需要引入三种资源:JS, CSS, SWF。
方法1.直接引入文件
这里我们使用完全压缩版的webuploader.min.js,同时还要引入Uploader.swf 、 webuploader.css,所以可以删除其他版本的文件,只留这三个文件,将解压的webuploader文件夹直接放在static文件夹下.

在index.html中引入webuploader.min.js

<script src="./static/webuploader-0.1.5/webuploader.min.js"></script>

在这里插入图片描述
重启项目后报错了,说缺少依赖jquery,打开源码webuploader.js看一下
在这里插入图片描述
原来webuploader是依赖于juqery或者Zepto的,那我们引入jquery,我们去jquery官网下载jquery,并在index.html中引入,注意,一定要在webuploader.min.js之前引入,在这里我下载的是1.12.4版本

<script src="./static/webuploader-0.1.5/jQuery1.12.4.js"></script>

方法2:模块化引入
下载webuploder

npm install webuploader --save

下载jquery

npm install jquery@1.12.4

在App.vue中引入webuploder和jquery

import $ from 'jquery'
import WebUploader from 'webuploader'

3.实例

upload.vue

<template>
    <div id="uploader" class="wu-example">
      <!--用来存放文件信息-->
      <div id="fileLilst" class="uploader-list"></div>
          <div class="btns">
            <!-- 选择文件的按钮 -->
              <div id="picker">选择文件</div>
            <!-- 开始上传按钮 -->
              <button id="uploadBtn" class="btn btn-default">开始上传</button>
      </div>
    </div>
</template>
<script>
import $ from 'jquery'
import WebUploader from 'webuploader'
var fileMd5;
//自定义参数 文件名
var fileName, uploader;
export default {
    name: 'upload',
	mounted() {
		this.getAllFileList()
      this.uploadPlan = `上传完成(${this.fileNum} / ${this.completeNum}`

      //监听分块上传过程中的三个时间点  
      WebUploader.Uploader.register({
        "before-send-file": "beforeSendFile",  //整个文件上传前调用
        "before-send": "beforeSend",  //每个分片上传前
        "after-send-file": "afterSendFile",  //分片上传完毕
      }, {
        //时间点1:所有分块进行上传之前调用此函数  
        beforeSendFile: function (file) {
          //console.log("beforeSendFile");
          var deferred = WebUploader.Deferred();
          //1、计算文件的唯一标记,用于断点续传  
          (new WebUploader.Uploader()).md5File(file, 0, 2 * 1024 * 1024)
            .progress(function (percentage) {
              $('#item1').find("p.state").text("正在读取文件信息...");
            })
            .then(function (val) {
              fileMd5 = val;
              $('#item1').find("p.state").text("成功获取文件信息...");
              //获取文件信息后进入下一步  
              deferred.resolve();
            });
          return deferred.promise();
        },
        //时间点2:如果有分块上传,则每个分块上传之前调用此函数  
        beforeSend: function (block) {
          console.log("beforeSend111111");
          console.log(block.chunk);
          var deferred = WebUploader.Deferred();
          $.ajax({
            type: "POST",
            url: "http://58.251.218.38:8080/BIMService2/model/checkOrMerge?action=checkChunk",
            data: {
              //文件唯一标记  
              fileMd5: fileMd5,
              //当前分块下标  
              //chunk:block.chblocknk, 
              chunk: block.chunk,
              //当前分块大小  
              chunkSize: block.end - block.start,
              userId: localStorage.getItem("userId")
            },
            dataType: "json",
            success: function (response) {
              if (eval('(' + response.ifExist + ')')) {
                //console.log("分片存在:" + block.chunk)
                //分块存在,跳过  
                deferred.reject();
              } else {
                //console.log("分片不存在:" + block.chunk)
                //分块不存在或不完整,重新发送该分块内容  
                deferred.resolve();
              }
            }
          });
          this.owner.options.formData.fileMd5 = fileMd5;
          console.log("继续执行")
          //deferred.resolve();  
          return deferred.promise();
        },
        //时间点3:所有分块上传成功后调用此函数  
        afterSendFile: function (file) {
          //console.log("afterSendFile");
          fileName = file.name; //为自定义参数文件名赋值
          //如果分块上传成功,则通知后台合并分块  
          $.ajax({
            type: "POST",
            url: "http://58.251.218.38:8080/BIMService2/model/checkOrMerge?action=mergeChunks",
            data: {
              fileMd5: fileMd5,
              fileName: fileName,
              ext: file.ext, //文件扩展名
              projectName: $("#project option:selected").text(), //项目名称
              userId: localStorage.getItem("userId")
            },
            success: function (response) {
              console.log(response)
              //alert("上传成功");   
            }
          });
        }
      });
      uploader = WebUploader.create({
        swf: 'static/webuploader/Uploader.swf', // swf文件路径
        formData: { projectName: "", userId: localStorage.getItem("userId") },
        server: 'http://58.251.218.38:8080/BIMService2/model/upload', // 文件接收服务端。
        pick: '#picker', // 选择文件的按钮。可选
        chunked: true, //是否要分片处理大文件上传
        chunkSize: 2 * 1024 * 1024, //分片上传,每片5M,默认是5M
        auto: true, //选择文件后是否自动上传
        chunkRetry: 2, //如果某个分片由于网络问题出错,允许自动重传次数
        //runtimeOrder: 'html5,flash',
        // 在上传当前文件时,准备好下一个文件
        prepareNextFile: false,
        threads: 1, //threads {Boolean} [可选] [默认值:3] 上传并发数。允许同时最大上传进程数。
        duplicate: false,//是否重复上传(同时选择多个一样的文件),true可以重复上传  
        /* accept: {
          title: '语音上传',
          extensions: 'wav,zip,rar',
          mimeTypes: 'audio/x-wav,.zip,.rar'
        } */
      });
      this.initWebUpload()
	},
	methods: {
		initWebUpload() {
		//当文件被加入队列之前触发
            uploader.on('beforeFileQueued', (file, data) => {
               //console.log('beforeFileQueued')
                    $.ajax({  
                        type:"POST",  
                        url:"http://58.251.218.38:8080/BIMService2/model/permissionVerification",  
                        data:{  
                            userId: localStorage.getItem("userId")
                        },  
                        dataType:"json",  
                        success (response){  
                            let msg = response.message
                            if (msg === '请先登录账号') {
                                this.$message.error(msg);
                                this.$router.push({path: '/Login'});
                                return false;
                            } else if (msg === '您没有使用权限,请先联系管理员获取使用权限') {
                                this.$message.error(msg);
                            }
                        }
                    }); 
            });
            // 当有文件被添加进队列的时候
            uploader.on('fileQueued', (file) => {
                //console.log('fileQueued')
                this.filesList.push({
                    id: file.id,
                    name: file.name,
                    size: this.reducedUnit(file.size),
                    percentage: 0
                })
                this.fileNum = this.filesList.length
            });
            //绑定uploadBeforeSend事件来给每个独立的文件添加参数
            uploader.on('uploadBeforeSend', (block, data) => {
                //设置data参数
                //data.projectName = $("#project").find("option:selected").text();   // 将存在file对象中的md5数据携带发送过去。
            }, 2);
            // 文件上传过程中创建进度条实时显示。
            uploader.on('uploadProgress', (file, percentage) => {
                //console.log('uploadProgress')
                this.filesList.forEach(item=>{
                    if(file.id===item.id) {
                        item.percentage = (percentage.toFixed(2))*100+"%"
                    }
                })
            });
            // 文件上传成功
            uploader.on( 'uploadSuccess', (file, response)=> {
                //console.log('uploadSuccess')
                //console.log(response._raw); //这里可以得到后台返回的数据
                this.filesList.forEach(item=>{
                    if(file.id===item.id) {
                        item.percentage = '上传成功'
                    }
                })
                this.completeNum++
                this.getAllFileList()
            });

            // 文件上传失败,显示上传出错
            uploader.on('uploadError', (file, ret) => {
                //console.log('上传失败')
                this.filesList.forEach(item=>{
                    if(file.id===item.id) {
                        item.percentage = '上传失败'
                        }
                    })
            });
            // 完成上传完
            uploader.on('uploadComplete', (file) => {
                $('#' + file.id).find('.progress').fadeOut();
            });
        },
        //暂停上传
        pauseUpload () {
            uploader.cancelFile(uploader.getFiles()[0].id);
        },
        //取消上传
        removeFile (index, row) {
            //this.filesList.splice(this.filesList.indexOf(row.name), 1);
            this.filesList.splice(index, 1)
        },
    }
}

4.遇到的问题

1)WebUploader 插件的上传按钮点击无效,按F12 之后才有反应
问题:上传按钮无效,debug的时候发现(上传id元素下面插件的渲染的宽度:1px,高度:1px),下面是错误图例说明:
在这里插入图片描述
解决方案:
在页面加一段样式:

<style>  
    #picker div:nth-child(2){width:100%!important;height:100%!important;}  
</style> 

如果上传按钮用的不是div 标签,改为div 标签,如<span id="picker">选择图片,改为<div id="picker">选择图片。

如果做了第一步但用的是span 标签的话,只有鼠标在文字下方的按钮区域才有效(有效时,鼠标移上去按钮颜色会变深,无效时按钮没反应),按F12之后,只有鼠标在文字上方的按钮区域点击才有效;

用div 的话就没这个问题,整个按钮都正常。
2)修改按钮样式

<style>
.webuploader-container {
   position: relative;
}
.webuploader-element-invisible {
   position: absolute !important;
   clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
    clip: rect(1px,1px,1px,1px);
}
.webuploader-pick {
   position: relative;
   display: inline-block;
   cursor: pointer;
   background: #3376ff;
   padding: 8px 12px;
   color: #fff;
   font-size: 14px;
   text-align: center;
   border-radius: 3px;
   overflow: hidden;
}
.webuploader-pick-hover {
   background: #065ffc;
}
</style>

参考网址:
https://blog.csdn.net/Easy_____/article/details/78250736
https://www.cnblogs.com/ocean-sky/p/7575980.html


版权声明:本文为qq_33414883原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。