vue-simple-uploader 实现断点续传

因为项目需求是网盘上传文件,但是普通上传文件如果文件太大,会造成反应过慢或者请求超时的问题,后面思考很久,和后台商量改成断点续传去实现,后面直接使用vue-simple-uploader插件实现。

安装

npm install vue-simple-uploader --save

在main.js初始化

import uploader from 'vue-simple-uploader'
Vue.use(uploader)

vue中代码(参考)

 <!-- 上传器 -->
  <uploader
    ref="uploader"
    :options="options"
    :autoStart="false"
    :file-status-text="fileStatusText"
    @file-added="onFileAdded"
    @file-success="onFileSuccess"
    @file-error="onFileError"
    class="uploader-ui"
  >
    <uploader-unsupport></uploader-unsupport>
    <uploader-drop>
      <div>
        <uploader-btn id="global-uploader-btn" :attrs="attrs" ref="uploadBtn"
          >选择文件<i class="el-icon-upload el-icon--right"></i
        ></uploader-btn>
      </div>
    </uploader-drop>
    <uploader-list></uploader-list>
  </uploader>

data数据定义

 options: {
        //目标上传 URL,默认POST
        target: "api/uploader/chunk",
        // target: process.env.VUE_APP_BASE_API+"api/uploader/chunk",
        //分块大小(单位:字节)
        chunkSize: "2048000",
        //上传文件时文件内容的参数名,对应chunk里的Multipart对象名,默认对象名为file
        fileParameterName: "upfile",
        //失败后最多自动重试上传次数
        maxChunkRetries: 3,
        //是否开启服务器分片校验,对应GET类型同名的target URL
        testChunks: true,
        query:{             //携带参数
           id:this.parentId,
           columnType:this.columnType
        },
        /* 
                    服务器分片校验函数,判断秒传及断点续传,传入的参数是Uploader.Chunk实例以及请求响应信息
                    reponse码是successStatuses码时,才会进入该方法
                    reponse码如果返回的是permanentErrors 中的状态码,不会进入该方法,直接进入onFileError函数 ,并显示上传失败
                    reponse码是其他状态码,不会进入该方法,正常走标准上传
                    checkChunkUploadedByResponse函数直接return true的话,不再调用上传接口
                    */
        checkChunkUploadedByResponse: function (chunk, response_msg) {
          console.log(response_msg)
          let objMessage = JSON.parse(response_msg);
          if(objMessage.status == "415" ){
            return true;
          }
          if (objMessage.skipUpload) {
            return true;
          }
          return (
            (objMessage.uploadedChunks || []).indexOf(chunk.offset + 1) >= 0
          );
        },
      },
      attrs: {
        accept: ACCEPT_CONFIG.getAll(),   //自己封装的 文件格式  
      },
      fileStatusText: {
        success: "上传成功",
        error: "上传失败",
        uploading: "上传中",
        paused: "暂停",
        waiting: "等待上传",
      },

方法

  onFileAdded(file) {
      this.computeMD5(file);
    },
    /*
            第一个参数 rootFile 就是成功上传的文件所属的根 Uploader.File 对象,它应该包含或者等于成功上传文件;
            第二个参数 file 就是当前成功的 Uploader.File 对象本身;
            第三个参数就是 message 就是服务端响应内容,永远都是字符串;
            第四个参数 chunk 就是 Uploader.Chunk 实例,它就是该文件的最后一个块实例,如果你想得到请求响应码的话,chunk.xhr.status就是
            */
    onFileSuccess(rootFile, file, response, chunk) {
      //refProjectId为预留字段,可关联附件所属目标,例如所属档案,所属工程等
      file.refProjectId = "123456789";
      file.id =this.parentId;
      file.columnType = this.columnType
      mergeFile(file)
        .then((responseData) => {
          if (responseData.data.code === 415) {
            console.log("合并操作未成功,结果码:" + responseData.data.code);
          }
        })
        .catch(function (error) {
          console.log("合并后捕获的未知异常:" + error);
        });
    },
    onFileError(rootFile, file, response, chunk) {
      console.log("上传完成后异常信息:" + response);
    },

    /**
     * 计算md5,实现断点续传及秒传
     * @param file
     */
    computeMD5(file) {
      file.pause();
      console.log(file)
      //单个文件的大小限制2G
      let fileSizeLimit = 2 * 1024 * 1024 * 1024;
      console.log("文件大小:" + file.size);
      console.log("限制大小:" + fileSizeLimit);
      if (file.size > fileSizeLimit) {
        this.$message({
          showClose: true,
          message: "文件大小不能超过2G",
        });
        file.cancel();
      }
      
      let fileReader = new FileReader();
      let time = new Date().getTime();
      let blobSlice =
        File.prototype.slice ||
        File.prototype.mozSlice ||
        File.prototype.webkitSlice;
      let currentChunk = 0;
      const chunkSize = 10 * 1024 * 1000;
      let chunks = Math.ceil(file.size / chunkSize);
      let spark = new SparkMD5.ArrayBuffer();
      //由于计算整个文件的Md5太慢,因此采用只计算第1块文件的md5的方式
      let chunkNumberMD5 = 1;

      loadNext();

      fileReader.onload = (e) => {
        spark.append(e.target.result);

        if (currentChunk < chunkNumberMD5) {
          loadNext();
        } else {
          let md5 = spark.end();
          file.uniqueIdentifier = md5;
          file.resume();
          console.log(
            `MD5计算完毕:${file.name} \nMD5:${md5} \n分片:${chunks} 大小:${
              file.size
            } 用时:${new Date().getTime() - time} ms`
          );
        }
      };

      fileReader.onerror = function () {
        this.error(`文件${file.name}读取出错,请检查该文件`);
        file.cancel();
      };

      function loadNext() {
        let start = currentChunk * chunkSize;
        let end =
          start + chunkSize >= file.size ? file.size : start + chunkSize;

        fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
        currentChunk++;
        console.log("计算第" + currentChunk + "块");
      }
    },
    close() {
      this.uploader.cancel();
    },
    error(msg) {
      this.$notify({
        title: "错误",
        message: msg,
        type: "error",
        duration: 2000,
      });
    },

存在问题:

1.options.target的请求路径,如果按照例子这样写的话,会存在发起请求的时候会出现携带路由的问题,这样的话 就要把子级路由设置成为一级路由,这样就可以正常发起请求了,如果直接写完整的请求路径的话,就不会存在这个问题

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
现在大部分的网站使用的是标准HTML的上传方式来上传文件。一般情况下标准HTML方式在网页中只能上传4MB左右的文件,如果访问的用户比较多的时侯这种方式容易上传失败。虽然标准HTML上传方式开发起来比较简单,但是这种方式用户体验比较差,上传的文件大小受到限制,所以如果我们需要上传上百或者更大的上G的文件时,HTML标准上传方式是无法满足我们的需求的。 而另一方面,随着互联网行业的发展用户产生的新的需求也越来越多,同时对用户体验也提出了更高的要求,传统的HTML方式也越来越难已满足新的用户需求。现在大部分的用户有文件批量上传的需求,希望只通过点击一次鼠标就能够批量的上传多张图片,而不是一张张的选择文件上传,这样操作即浪费时间又非常烦琐。 近年来,由于数码和影视行业的迅猛发展刺激了用户对大文件的上传需求,现在越来越多的用户希望能够通过WEB的方式上传更大的文件,比如电影和图片。这些类型的文件通常都非常大,一般都在500MB以上,高清的影视文件至少在1G以上。这样的大文件是根本无法通过标准HTML方式来上传的。 不仅如此,由于国内网络环境比较特殊,有许多地区的网络不够稳定,在上传文件的过程中可能会发生断网的情况。如果用户正在上传一个1000MB的文件,已经上传了500MB,这时网络出现问题上传中止了。那么下一次用户需要要重新上传前面的500MB,而不是从500MB开始上传,这将浪费用户的许多时间。 新颖网络HTTP文件断点续传控件是专门用于解决HTTP大文件上传的需求而开发的产品。通过我们的HttpPartition模块用户能够非常方便的一次性选择超过200个的文件。而且我们升级了用户体验,用户现在不仅能够通过点击按钮来选择多个文件,还可以通过HttpDroper来拖拽文件甚至是文件夹。 现在我们能够轻松支持2G左右的大文件上传。为了减轻服务器的压力在HttpUploader模块中我们并不是一次上传2G的数据,而是将2G化分为小的数据块,每次向服务器上传约128KB左右的数据。同时在每次上传的数据中附带了文件大小,起始位置,文件MD5等信息。对于开发人员来说,有了这些信息,断点续传功能将会变的和普通的文件上传功能一样简单。 相信新颖网络HTTP断点续传控件能够帮助您赢利市场。 产品介绍:[url=http://www.cnblogs.com/xproer/archive/2012/02/17/2355440.html][/url]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值