根据部门的业务需求,需要在网络状态不良的情况下上传很大的文件(1G+)。
其中会遇到的问题:
1,文件过大,超出服务端的请求大小限制;
2,请求时间过长,请求超时;
3,传输中断,必须重新上传导致前功尽弃。
解决方案实现思路,拿到文件,保存文件唯一性标识,切割文件、分片上传、文件MD5验证、断点续传、手动重试上传。

鉴于过往有使用过webupload文件上传组件的经验,于是此次采用的是Plupload作为替换。Plupload是一款由著名的web编辑器TinyMCE团队开发的上传组件,简单易用且功能强大。

Plupload有以下功能和特点

  1. 拥有多种上传方式:HTML5、flash、silverlight以及传统的<input type=”file” />。Plupload会自动侦测当前的环境,选择最合适的上传方式,并且会优先使用HTML5的方式。所以你完全不用去操心当前的浏览器支持哪些上传方式,Plupload会自动为你选择最合适的方式。
  2. 支持以拖拽的方式来选取要上传的文件
  3. 支持在前端压缩图片,即在图片文件还未上传之前就对它进行压缩
  4. 可以直接读取原生的文件数据,这样的好处就是例如可以在图片文件还未上传之前就能把它显示在页面上预览
  5. 支持把大文件切割成小片进行上传,因为有些浏览器对很大的文件比如几G的一些文件无法上传。

环境

  • vue2.x
  • webpack3.x
  • axios

代码

npm安装plupload,文件引入组件,

1
2
3
4
5
6
7
8
9
10
11
12
<uploader browse_button="upload_area"
                :max_retries="3"
                :url="action"
                :headers="headers"
                chunk_size="10MB"
                drop_element="upload_area"
                @disableBrowse="!loading"
                :BeforeUpload="beforeUpload"
                :ChunkUploaded="chunkUploaded"
                :FilesAdded="filesAdded"
                :StateChanged="stateChanged"
                @inputUploader="inputUploader" />

  

初始化方法filesAdded(),每次上传前清空队列的其他文件,保证上传的一致性。其次对文件类型进行判断过滤fileType(),文件进入时进行总md5一次fileMd5(),然后进入文件分片chunkCheckStatus(),每个分片都要进行md5并与后台进行校验fileMd5(),确保文件在中断后继续上传的准确性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
filesAdded (up, files) {
      // 删除上传队列中其他文件,只保留最近上传的文件
      let fileLen = files.length, that = this
      if (fileLen > 1) {
        files = files.splice(0, fileLen - 1)// 清空上传队列
      }
      files.forEach((f) => {
        f.status = -1
        that.dataForm.file = f
        that.fileType(f.getNative())
        if (that.loading) {
          that.computeStatus = true
          that.progress = 0
          // 文件分片
          let chunkSize = 2097152, // Read in chunks of 2MB
            chunks = Math.ceil(f.size / chunkSize)
          that.fileMd5(f.getNative(), (e, md5) => {
            that.dataForm.md5 = md5
            if (that.loading == true) {
              that.count = 0
              that.chunkCheckStatus(md5, that.dataForm.fileName, (uploader, dataList) => {
                that.uploading = uploader
                if (that.uploading == true) {
                  for (let chunk = 1; chunk <= chunks; chunk++) {
                    that.fileChunkFile(f.getNative(), chunk, (e, chunkFile) => {
                      that.fileMd5(chunkFile, (e, blockMd5) => {
                        that.PostFile(up, chunkFile, chunk, chunks, md5, blockMd5)
                      })
                    })
                  }
                else {
                  // 去重
                  that.progress = 0
                  for (let chunk = 1; chunk <= chunks; chunk++) {
                    let status = 0
                    dataList.some((item) => {
                      if (item.chunk == chunk) {
                        status = 1
                        return false
                      }
                    })
                    if (status == 0) {
                      that.fileChunkFile(f.getNative(), chunk, (e, chunkFile) => {
                        that.fileMd5(chunkFile, (e, blockMd5) => {
                          that.PostFile(up, chunkFile, chunk, chunks, md5, blockMd5)
                        })
                      })
                    }
                  }
                }
              })
            }
          })
        }
      })
    }

  

文件md5方法,这里使用了SparkMD5,import SparkMD5 from 'spark-md5'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
fileMd5 (file, callback) {
      let that = this
      var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
        file = file,
        chunkSize = 2097152, // Read in chunks of 2MB
        chunks = Math.ceil(file.size / chunkSize),
        currentChunk = 0,
        spark = new SparkMD5.ArrayBuffer(),
        fileReader = new FileReader()
      fileReader.onload = function (e) {
        console.log('read chunk nr', currentChunk + 1, 'of', chunks)
        spark.append(e.target.result) // Append array buffer
        currentChunk++
        if (currentChunk < chunks) {
          loadNext()
        else {
          let blockMd5 = ''
          blockMd5 = spark.end()
          callback(null, blockMd5)
        }
      }
      fileReader.onerror = function () {
        callback('oops, something went wrong.')
      }
      function loadNext () {
        var start = currentChunk * chunkSize,
          end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize
        fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
      }
      loadNext()
    }

  

文件分片上传方法,验证总分片信息后,把每个分片进行md5加密并上传校验,这里有写进度条相关的控制,不一一展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
chunkCheckStatus (md5, fileName, callback) {
      this.$http({
        url: this.$http.adornUrl('/biz/upload/getFileBlockStatus'),
        method: 'get',
        params: this.$http.adornParams({
          md5: md5,
          fileName: fileName
        })
      }).then(({ data }) => {
        if (data && data.code === 0) {
          if (data.list != null) {
            this.uploading = false
            this.chunkCheckData = []
            data.list.map((item, index) => {
              if (item.isUpload == true) {
                this.count++
                this.chunkCheckData.push(item)
              }
            })
            callback(this.uploading, this.chunkCheckData)
            return
          }
          this.uploading = true
          callback(this.uploading)
        else {
          this.$message.error(data.msg)
          this.loading = false
          this.computeStatus = false
          return false
        }
      })
    }

  

详细的配置信息可以参考我写的这篇文章:http://blog.ncmem.com/wordpress/2019/08/09/vue%e5%a4%a7%e6%96%87%e4%bb%b6%e6%96%ad%e7%82%b9%e7%bb%ad%e4%bc%a0/

vue+大文件断点续传的更多相关文章

  1. iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载+使用输出流代替文件句柄

    前言:本篇讲解,在前篇iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载的基础上,使用输出流代替文件句柄实现大文件断点续传.    在实际开发中,输入输出流用的比较少,但 ...

  2. php实现大文件断点续传下载实例

    php实现大文件断点续传下载实例,看完你就知道超过100M以上的大文件如何断点传输了,这个功能还是比较经典实用的,毕竟大文件上传功能经常用得到. require_once('download.clas ...

  3. vue大文件上传控件选哪个好?

    需求: 项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在20G内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以20G来进行限制. PC端全平台支持,要求支持Window ...

  4. HTML5 大文件断点续传完整思路整理

    需求: 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验: 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包 ...

  5. B/S大文件断点续传

    一. 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件夹进行上传:支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传.刷新页面后继续传输. ...

  6. vue+大文件分片上传

    最近公司在使用vue做工程项目,实现大文件分片上传. 网上找了一天,发现网上很多代码都存在很多问题,最后终于找到了一个符合要求的项目. 工程如下: 对项目的大文件上传功能做出分析,怎么实现大文件分片上 ...

  7. webUploader大文件断点续传学习心得 多文件

    二.Jsp代码: <!-- 断点续传   start--> <!-- 隐藏域 实时保存上传进度 --> <input id="jindutiao" t ...

  8. js解决大文件断点续传

    最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...

  9. .net解决大文件断点续传

    以ASP.NET Core WebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API ,包括文件的上传和下载. 准备文件上传的API #region 文件上传  ...

随机推荐

  1. iptables详解说明

    Iptabels是与Linux内核集成的包过滤防火墙系统,几乎所有的linux发行版本都会包含Iptables的功能.如果 Linux 系统连接到因特网或 LAN.服务器或连接 LAN 和因特网的代理 ...

  2. 安装Vue脚手架和创建一个简单的Demo

    https://www.cnblogs.com/pengjunhao/p/6762141.html https://www.cnblogs.com/yanxulan/p/8978732.html 查看 ...

  3. 标准库类型之vector

    上篇中遗留了一个小作业,就是用string中的find_first_not_of和find_last_not_of函数来实现字符串左右空格的去除,先来完成它,实现的思路是先来编写去除左空格,然后再编写 ...

  4. 【C++/html版 代码 : 暴力破解数字红包 】-- 只要有编译器或者,不看运气,用手速敲代码说话,多人合作效果更佳!

    需求分析: 或者是更大的范围! 是不是很捉急!运气背点不就over了! C++版: #include <stdio.h> #include <stdlib.h> #includ ...

  5. usb相关

    https://github.com/daynix/UsbDk/tree/master/UsbDk 更应该关注下libusb

  6. 开启树莓派自带的VNC功能

    前期准备 树莓派可以连接路由器或连上wifi,我用的是自己的小米路由器,目的是为了获取内网IP 工具准备 下载 vnc viewer https://www.realvnc.com/en/connec ...

  7. 三种方法给Vmware虚拟机占用空间清理瘦身

    随着VMware虚拟机使用时间的增长,其所占用的空间也越来越大,本文来说说怎么给VMware虚拟机占用的空间进行瘦身. 方法一:VMware自带的清理磁盘这个方法是VMware自带,具有普适性,对快照 ...

  8. Lua 学习之基础篇八<Lua 元表(Metatabble)&&继承>

    讲到元表,先看一段table的合并动作. t1 = {1,2} t2 = {3,4} t3 = t1 + t2 attempt to perform arithmetic on a table val ...

  9. Java中String为什么是不可变

    什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的.不 ...

  10. BZOJ 5494: [2019省队联测]春节十二响 (左偏树 可并堆)

    题意 略 分析 稍微yy一下可以感觉就是一个不同子树合并堆,然后考场上写了一发左偏树,以为100分美滋滋.然而发现自己傻逼了,两个堆一一对应合并后剩下的一坨直接一次合并进去就行了.然鹅我这个sb把所有 ...