大文件分片断点续传

<template>
  <div class="hello">
    <el-upload class="upload-demo" drag :on-change='change' :auto-upload='false' action multiple>
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
      <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
    </el-upload>
    {{total}}
    <el-progress :text-inside="true" :stroke-width="26" :percentage="total"></el-progress>
    <el-button @click="handelBtn">{{btn?'继续':'暂停'}}</el-button>
  </div>
</template>

<script>
  import SparkMD5 from 'spark-md5'
  import axios from 'axios'
  import qs from 'qs'
  export default {
    name: 'HelloWorld',
    data() {
      return {
        img: null,
        msg: 'Welcome to Your Vue.js App',
        total: 0,
        video: null,
        btn: false,
        abort:false,
        partList:[],
        hash:''
      }
    },
    methods: {
      async change(file) {
        file = file.raw
        let fileReader = new FileReader()
        fileReader.readAsArrayBuffer(file)
        let buffer = null
        // console.log(SparkMD5);

        //1. 解析为buffer数据
        fileReader.onload = ev => {
          buffer = ev.target.result
          console.log(buffer);
          
          // 2. 使用SparkMD5
          let spark = new SparkMD5.ArrayBuffer()
          spark.append(buffer)
          // 3.获取hash值
          let hash = spark.end()
          // 4.截取文件后缀
          let suffix = /\.([0-9a-zA-Z]+)$/i.exec(file.name)[1]
          console.log(suffix);

          // 切片
          let partList = []
          // 单个切片大小 (切100片)
          let partSize = Math.ceil(file.size / 100)
          // 纪录当前切到哪
          let cur = 0
          for (let i = 0; i < 100; i++) {
            let item = {
              chunk: file.slice(cur, cur + partSize),
              filename: `${hash}_${i}.${suffix}`,
            }
            cur += partSize
            partList.push(item)
          }
          this.partList = partList
          this.hash = hash
          this.sendRequest(this.partList, this.hash)
        }


      },
      // 上传分片
      async sendRequest() {
        // 根据切片做100请求
        let requestList = []
        this.partList.forEach((item, index) => {
          // 每一个fn就是发送一个切片请求
          let fn = () => {
            let formDate = new FormData()
            formDate.append('chunk', item.chunk)
            formDate.append('filename', item.filename)
            return axios.post('每一片请求接口', formDate, {
              headers: {
                "content-Type": 'multipart/form-data'
              }
            }).then(res => {
              // debugger
              if (res.data.code == 0) {
                this.total += 1
                // 传完切片移除掉 为了实现断点续传
                this.partList.splice(index, 1)

              }
            })
          }
          requestList.push(fn)
          // console.log(requestList);

        })
        // 传递
        let i = 0
        let complete = async () => {
          console.log('complete')
          let result = await axios.post('上传全部后的接口', {
            params: {
              hash: this.hash
            }
          })
          console.log(result)

          result = result.data
          if (result.code = 0) {
            this.video = result.path
          }
        }

        console.log(requestList.length, '----');

        let send = async () => {
          // 已经终端则不在上传
          if(this.abort) return
          if (i >= requestList.length) {
            // 全部上传成功
            complete()
            return
          }
          console.log(i, '====');

          await requestList[i]()
          i++
          send()
        }
        send()

      },
      handelBtn() {
        if(this.btn) {
          // 断点续传
          this.btn = false
           this.abort = false
           this.sendRequest()
          return
        } 
        // 暂停上传
        this.btn = true
        this.abort = true
      },
    }
  }

</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  h1,
  h2 {
    font-weight: normal;
  }

  ul {
    list-style-type: none;
    padding: 0;
  }

  li {
    display: inline-block;
    margin: 0 10px;
  }

  a {
    color: #42b983;
  }

</style>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值