设为首页 加入收藏

TOP

Vue.js实现大文件分片md5断点续传(一)
2019-09-17 18:14:16 】 浏览:30
Tags:Vue.js 实现 文件 分片 md5 断点

背景

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

<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(),确保文件在中断后继续上传的准确性。

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'

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()
        } el
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇JavaScript定时器(Timer) 下一篇深入V8引擎-AST(2)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目