根据部门的业务需求,需要在网络状态不良的情况下上传很大的文件(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. cannot find -llapack + -lblas

    问题: cannot find -llapack + -lblas 解决: sudo apt-get install libblas-dev liblapack-dev 转:https://suppo ...

  2. HRNet网络结构

    最近正在阅读CVPR2019的论文Deep High-Resolution Representation Learning for Human Pose Estimation. 无奈看论文中的Netw ...

  3. python3 模块和包

    一.模块(Module)和包(Package) 1.模块:一个包含所有你定义的函数和变量的文件,其后缀名是 .py ,一个.py文件就是一个模块 2.包:一定包含 __init__.py模块 的文件夹 ...

  4. ZZNUOJ-2157: 水滴来袭-【干扰阅读-卡模糊精度1e-8的问题】

    ZZNUOJ-2157: 水滴来袭 那是一个冷雨霏霏的秋天的下午,当罗辑拿着枪威胁三体文明的时候,如果过了三十秒三体人还没有同他展开谈判,罗辑就会扣动扳机即刻结束自己的生命,随后他身上的核弹控制器就会 ...

  5. 如何创建javabeans实例

    如何创建javabeans实例 1.像使用普通java类一样,创建javabean实例 创建一个用户类的javabeans package com.po; /** * * 用户类 * @author ...

  6. PHP mysqli_connect_error() 函数

    返回上一次连接错误的错误描述: <?php $con=mysqli_connect("localhost","wrong_user","my_p ...

  7. 五十一.Openstack概述 部署安装环境 、 部署Openstack OpenStack操作基础

    虚拟化技术的底层构成: 内核的虚拟化模块(KVM):从内核集去提供虚拟化及CPU指令集的支持,要求CPU支持,(CPU有VMX指令集)   硬件仿真层(QEMU):虚拟一些周边设备,鼠标.键盘.网卡. ...

  8. [Luogu] 染色

    https://www.luogu.org/problemnew/show/P2486 qizha 为什么会wa #include <cstdio> #include <cmath& ...

  9. nios ii 13 主程序的函数可以用Open Declaration 查看,但是编译的时候却说 undefined reference to 。。。这是为什么?

    在做12864 ip 核试验时,写了三个文件第一个是时序文件QC12864.v第二个是QC12864.H这个文件主要包括声明和宏定义,第三个文件是QC12864.c这个文件包含函数的定义.详细的请看  ...

  10. 自制 yum 源仓库

    转自:https://www.cnblogs.com/marility/p/7278374.html 背景 客户服务器为内网机器,centos7系统,且无法与外网连接.需要部署对应的LANMP环境及其 ...