前端实现MD5加密分片上传

前言:每次上传遇到大文件,上传速度和上传后接口响应都比较慢,为了提高用户体验,减少用户的等待时间,缓解服务器的压力。我们 对大文件进行了分片上传,下面的具体思路和完整代码,有需要的小伙伴可以看看。

实现思路:

1. 文件 MD5 加密

MD5 是文件的唯一标识,可以利用文件的 MD5 查询文件的上传状态。

根据文件的内容、文件名称、文件大小等信息,通过 spark-md5[2] 生成文件的 MD5。

2. 文件分片

文件上传优化的核心就是文件分片,Blob 对象中的 slice 方法可以对文件进行切割,File 对象是继承 Blob 对象的,因此 File 对象也有 slice 方法。看自己项目需要设置分片大小,我们分片大小和后端约定是5MB。

3. 上传分片

上传所有的切片,将切片序号、切片文件、文件 MD5 传给后台。

后台接收到上传请求后,首先查看名称为文件MD5 的文件夹是否存在。

思路很简单,实现起来大家肯定各自有难度,下面的完整的代码,结合不同项目可以参考一下:


import SparkMD5 from 'spark-md5'
import request from '@/api/request'
export const uploadByPieces = (file, option, url) => {
  return new Promise(async (resolve, reject) => {
    // 读取文件的md5
    let fileMD5
    let fileRederInstance = new FileReader()
    fileRederInstance.readAsBinaryString(file)
    fileRederInstance.addEventListener('load', (e) => {
      let fileBolb = e.target.result
      fileMD5 = SparkMD5.hashBinary(fileBolb)
      readChunkMD5(file, fileMD5, option)
    })

    // 针对每个文件进行chunk处理
    const readChunkMD5 = async (file, md5, option) => {
      const chunkSize = 5 * 1024 * 1024 // 5MB一片
      const chunkCount = Math.ceil(file.size / chunkSize) // 总片数
      for (var i = 0; i < chunkCount; i++) {
        const { chunk } = getChunkInfo(file, i, chunkSize)
        await uploadChunk({ chunk, currentChunk: i, chunkCount, md5 }, option)
      }
    }
    const getChunkInfo = (file, currentChunk, chunkSize) => {
      let start = currentChunk * chunkSize
      let end = Math.min(file.size, start + chunkSize)
      let chunk = file.slice(start, end)
      chunk = blobToFile(chunk, file.name)
      return { start, end, chunk }
    }
    // Blob 转 File
    const blobToFile = (blob, fileName) => {
      const file = new File([blob], fileName, { type: blob.type })
      return file
    }
    const uploadChunk = (chunkInfo, option) => {
      // 创建formData对象,下面是结合不同项目给后端传入的对象。
      let formData = new FormData()
      if (Object.keys(option).length > 0) {
        for (let key in option) {
          formData.append(key, option[key])
        }
      }
      formData.append('file', chunkInfo.chunk)
      formData.append('md5', chunkInfo.md5)
      formData.append('chunk_index', chunkInfo.currentChunk)
      formData.append('chunk_total', chunkInfo.chunkCount)
      request
        .post(url, formData)
        .then((res) => {
          if (res.data.src) {
            resolve(res)
          } else if (res.status !== 200) {
            reject(res)
          }
        })
        .catch((e) => {
          reject(e)
        })
    }
  })
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值