松鼠的博客

导航

前端处理大文件/视频分片上传,断点续传

1、html部分,项目使用的是ant-design-vue组件库;spark-md5进行加密上传

 

 

2、使用变量:(通过上传成功的分片数与总分片数对比判断上传是否完成)

 

 

3、主要方法:

1、 查询当前文件是否上传

 

 

2、获取文件的MD5编码

// 获取文件的MD5编码
    computedSliceMd5 (file) {
      this.file = file
      this.fileType = file.type
      this.blobSlice =
        File.prototype.mozSlice ||
        File.prototype.webkitSlice ||
        File.prototype.slice
      this.spark = new SparkMD5.ArrayBuffer()
      this.chunkSpark = new SparkMD5.ArrayBuffer()
      this.currChunkSpark = new SparkMD5.ArrayBuffer()
      this.totalFileReader = new FileReader()
      const checkFileNameOk = true
      if (checkFileNameOk) {
        this.chunks = Math.ceil(this.file.size / this.chunkSize)
        this.totalFileReader.onload = e => {
          this.spark.append(e.target.result)
          this.currChunkSpark.append(e.target.result)
          this.chunkSparkMd5 = this.currChunkSpark.end()
          this.tmpDataList[this.tmpDataList.length - 1].partMd5 = this.chunkSparkMd5 // 修改当前塞进去的片段的md5
          this.currentChunk++
          if (this.currentChunk < this.chunks) {
            this.loadNext()
          } else {
            // 文件的MD5身份标识
            this.identifier = this.spark.end()
            // 查询当前文件是否已上传
            this.checkIsUpload().then(res => { // 根据实际项目调用
              const md5Arr = []
              if (res.data.success) {
                res.data.data.part.forEach(item => {
                  if (item) {
                    md5Arr.push(item.filePartMd5)
                  }
                })
              }
              this.uploadedCount = md5Arr.length
              const isUpload = res.data.success && !md5Arr.length && res.data.data.full.fileName
              if (isUpload) {
                this.$message.error(`您上传的${file.name}已经上传过,请选中其他文件!`)
                this.uploading = false
                return
              }
              for (let i = 0; i < this.tmpDataList.length; i++) {
                if (md5Arr.indexOf(this.tmpDataList[i].partMd5) === -1) {
                  const requestCount = 0
                  const formData = new FormData()
                  formData.append('data', this.tmpDataList[i].file)
                  formData.append('fileName', this.uploadFileName)
                  formData.append('index', this.tmpDataList[i].currentNum)
                  formData.append('isTrancode', 0)
                  formData.append('md5', this.identifier)
                  formData.append('partMd5', this.tmpDataList[i].partMd5)
                  formData.append('size', this.file.size)
                  formData.append('total', this.chunks)
                  formData.append('platformCode', 'CMRH_IVARS')
                  if (!this.uploadFile(formData, requestCount)) {
                    this.$message.error(`您上传的${this.file.name}上传失败,如有需要请重新上传...`)
                    this.uploading = false
                    break
                  }
                }
              }
            })
          }
        }
        this.totalFileReader.onerror = function () {
          this.$message.error('读取文件出错,请重试')
          this.uploading = false
        }
        this.loadNext()
      } else {
      }
    },

3、文件切片

// 文件切片
    loadNext () {
      // 对每一片分片进行md5加密
      this.start = this.currentChunk * this.chunkSize
      this.end =
        this.start + this.chunkSize >= this.file.size
          ? this.file.size
          : this.start + this.chunkSize
      const pieceFile = this.blobSlice.call(this.file, this.start, this.end)
      pieceFile.name = this.file.name
      const tmpObj = {
        file: pieceFile,
        currentSize: this.end - this.start,
        currentNum: this.currentChunk + '',
        partMd5: this.chunkSpark.end()
      }
      this.tmpDataList.push(tmpObj)
      this.totalFileReader.readAsArrayBuffer(pieceFile)
    },

4、上传分片

// 上传分片
    async uploadFile (param, count) {
      const res = await axios.post(config.getVodUrl('/media/upload'), param, { headers: { 'Authorization': this.nucToken } })
      if (res.data.success) {
        this.uploadedCount++
        return true
      } else {
        count++
        if (count < 3) {
          this.uploadFile(param, count)
        } else {
          // 当前分片上传3次还未成功,不再上传,直接判定失败
          this.$message.error(res.data.message)
          this.uploading = false
          return true
        }
      }
    },

5、完成

 

 

 

参考文章:http://blog.ncmem.com/wordpress/2023/11/07/%e5%89%8d%e7%ab%af%e5%a4%84%e7%90%86%e5%a4%a7%e6%96%87%e4%bb%b6-%e8%a7%86%e9%a2%91%e5%88%86%e7%89%87%e4%b8%8a%e4%bc%a0%ef%bc%8c%e6%96%ad%e7%82%b9%e7%bb%ad%e4%bc%a0/

欢迎入群一起讨论

 

 

posted on 2023-11-07 11:01  Xproer-松鼠  阅读(86)  评论(0编辑  收藏  举报