大文件分片上传(自己备用,别人不一定看得懂)

9 篇文章 0 订阅
8 篇文章 0 订阅
<template>
  <div>
    <el-upload class="upload-demo"
               ref="upload"
               action="#"
               :file-list="fileList"
               :http-request="httpRequest">
      <el-button size="small"
                 type="primary">点击上传</el-button>
      <div slot="tip"
           class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
    </el-upload>
  </div>
</template>

<script>
export default {
  name: '',
  components: {},
  data() {
    return {
      fileList: [],
      accept: '.png,.mp3'
    }
  },
  methods: {
    // 自定义上传,实现分片上传
    httpRequest(param) {
      const chunkSize = 3 * 1024 * 1024 //每个片的大小为3M
      const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
      const hasFile = (file) => {
        return new Promise((resolve, reject) => {
          const chunks = Math.ceil(file.size / chunkSize)
          let currentChunk = 0
          const SparkMD5 = window.SparkMD5
          const spark = new SparkMD5()
          const fileReader = new FileReader()
          function loadNext() {
            const start = currentChunk + chunkSize
            const end = start + chunkSize >= file.size ? file.size : start + chunkSize
            fileReader.readAsBinaryString(blobSlice.call(file, start, end))
          }
          fileReader.onload = (e) => {
            spark.appendBinary(e.target.result)
            currentChunk += 1
            if (currentChunk < chunks) {
              loadNext()
            } else {
              const hexHash = spark.end()
              resolve(hexHash)
            }
          }
          fileReader.onerror = () => {
            this.$message.error('文件读取失败')
          }
          loadNext()
        })
      }
      async function handleUplaod() {
        const file = param.file
        const type = file.name.match(/[^\.]\w+$/)[0].toLowerCase()
        const uploadfile = this.$refs.upload.uploadfile
        let uploadfileIndex = 0
        if (!file) {
          this.$message.error('没有获取文件')
          return
        }
        if (!file.size) {
          this.$message.error('文件内容为空')
          return
        }
        if (this.accept && this.accept.indexOf(type) === -1) {
          this.$message.error('文件类型错误')
          return
        }
        if (file.size / 1024 / 1024 / 1024 / 5) {
          this.$message.error('文件大小不能超过5GB')
          return
        }
        uploadfile[getFileIndex(uploadfile, file.uid)].status = 'uploading'
        const blockCount = Math.ceil(file.size / chunkSize) //分片总数
        const hash = await hasFile(file) //文件md5
        let totalCount = 0
        checkFileStatus().then(res => {
          if (!res.md5) {
            // 服务器没有改文件 走上传
            for (let i = 0; i < blockCount; i++) {
              const start = i * chunkSize
              const end = Math.min(file.size, start + chunkSize)
              //参数
              const form = new FormData()
              form.append('file', blobSlice.call(file, start, end))
              form.append('filename', file.name)
              form.append('shardIndex', i)
              form.append('md5', hash)
              form.append('uid', file.uid)
              form.append('shardTotal', blockCount)
              // 上传
              uploadShards(form, { md5: hash, name: file.name, shardTotal: blockCount, uid: file.uid })
            }
          } else {
            // 有文件,直接拿文件数据
          }
        })

      }
      function getFileIndex() { return 0 }
      function uploadShards(form, params) {
        uploadShard(form).then(res => {
          totalCount++
          if (res.finishupload) {
            // 所以分片完成,走合并
            mege(params)
          } else {
            const uploadfile = this.$refs.upload.uploadFiles
            for (let index = 0; index < uploadfile.length; index++) {
              if (uploadfile[index].uid === file.uid && totalCount !== blockCount) {
                uploadfile[index].percentage = Math.floor(totalCount / blockCount * 100)
              }
            }
          }
        })
      }
      function mege(arg) {
        console.log(arg);
      }
      handleUplaod()
    }
  }
}
</script>

<style scoped>
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值