前端使用 切片 实现大文件上传

1、准备好一个简单的上传结构


<template>
  <el-upload
    class="upload-demo"
    action="#"
    :http-request="onHttpRequest"
  >
  <el-button size="small" type="primary">点击上传</el-button>
</el-upload>
</template>

<script>
export default {
  data () {
    return {

    }
  },

  created () {

  },

  methods: {
    onHttpRequest () {
      console.log(123)
    }
  }
}
</script>

2、把对象分割成多个文件流切片;固定数量 && 固定大小

onHttpRequest ({ file }) {
  console.log(file.size)
  // 每块大小
  const chunkSize = 5 * 1024
  // 切割次数
  const chunkCount = Math.ceil(file.size / chunkSize)
  // 文件切片 不是数组的slice 文件对象原型上的slice方法,继承自 Blob的slice 二进制数据
  // 创建一个FormData对象来存储文件片段和相关信息
  const formData = new FormData()
  for (let i = 0; i < chunkCount; i++) {
    formData.append('chunks', file.slice(i * chunkSize, i * chunkSize + chunkSize), '123')
  }
  this.uploadChunk(formData)
},

3、断点续传

// 切片上传
async uploadChunk (formData) {
  const chunk = formData.get('chunks', this.selectChunks)
  await axios({
    method: 'POST',
    url: '/upload',
    data: chunk
  })
  this.selectChunks++
  this.uploadChunk(formData)
}

4、合并文件

if (!chunk && this.selectChunks >= formData.getAll('chunks').length) {
  await axios({
    method: 'GET',
    url: '/merge'
  })
  return
}

5、文件秒传

文件秒传和文件续传不同,文件续传为继续上一次进行上传,而文件秒传为,上传过的文件或者文件切片后端通过标识对比,省略文件传输,如何生成文件标记和文件块标记?文件名字、索引都不是唯一值,真正唯一的是文件内容,所需要根据文件内容生成文件hash,借助spark-md5

5.1 安装 yarn add spark-md5

yarn add spark-md5

5.2 引入和使用

import SparkMd5 from 'spark-md5'
// 创建spark实例
const spark = new SparkMd5.ArrayBuffer()
// 将buffer数据处理为hash
spark.append(buffer)
// 返回hash
const hash = spark.end()

5.3 封装文件的方法

fileParse (file) {
  return new Promise(resolve => {
  // 创建读取文件的实例对象
    const fileReade = new FileReader()
    // 借助实例对象的方法读取文件流数据
    fileReade.readAsArrayBuffer(file)
    // 监听文件流数据读取成功的回调
    fileReade.onload = res => {
    // res.target.result 就是文件流数据
      resolve(res.target.result)
    }
  })
},

5.4 封装获取 hash 方法

async getFileHash (file) {
  const buffer = await this.fileParse(file)
  // 创建spark实例
  const spark = new SparkMd5.ArrayBuffer()
  // 将buffer数据处理为hash
  spark.append(buffer)
  // 返回hash
  return spark.end()
},

5.5 添加 hash 

async onHttpRequest ({ file }) {
  const fileHash = await this.getFileHash(file)
  // 每块大小
  const chunkSize = 5 * 1024
  // 切割次数
  const chunkCount = Math.ceil(file.size / chunkSize)
  // 文件切片 不是数组的slice 文件对象原型上的slice方法,继承自 Blob的slice 二进制数据
  // 创建一个FormData对象来存储文件片段和相关信息
  const formData = new FormData()
  for (let i = 0; i < chunkCount; i++) {
    const chunk = file.slice(i * chunkSize, i * chunkSize + chunkSize)
    const chunkHash = await this.getFileHash(file)
    formData.append('chunks', chunk, `${fileHash}:${chunkHash}`)
  }
  console.log(formData.getAll('chunks'))
  // this.uploadChunk(formData)
},

5.6 文件检查

// 文件检查
async checkFileExists (fileHash) {
  return axios({
    url: '/fileexists?hash=' + fileHash
  })
},
const fileHash = await this.getFileHash(file)
await checkFileExists()

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值