vue分片上传

33 阅读2分钟

上传的时候,可能会需要一个文件的唯一 标识,在上传文件的时候也要将文件的唯一标识(文件的MD5加密文件的字符串,每个文件的唯一标识)传递给后端,后端会通过该标识返回给我们告诉我们这个文件是否已经上传过,没有这个文件就需要我们全部上传,存在了,前端就不需要再上传,这个文件上传了一部分,需要把剩余的上传

这个文件的MD5唯一标识呢,也是通过spark-md5来获取,具体步骤 :
安装:
    npm i spark-md5
    
单独建个js文件,向外暴露出去 

method.js
        import SparkMD5 from 'spark-md5'

        // 获取文件的唯一MD5标识码
        export function getFileMd5(file) {
          return new Promise((resolve, reject) => {
            const fileReader = new FileReader()
            const spark = new SparkMD5.ArrayBuffer()
            fileReader.readAsArrayBuffer(file)
            fileReader.onload = e => {
              spark.append(e.target.result)
              let md5 = spark.end()
              resolve(md5)
            }
          })
        }
        
   提交的时候,我们让后台知道提交的是哪一部分
   <div class="index">
      <el-upload
        v-model:file-list="fileList"
        class="upload-demo"
        :auto-upload="false"
        :limit="1"
        :on-change="handleChange"
      >
        <el-button type="primary">Click to upload</el-button>
      </el-upload>
    </div>
    
    <script setup>
import { ref } from 'vue'
import { getFileMd5 } from './method'
 
const fileList = ref([])
 
// 文件上传 选择文件时触发(:on-change事件)
const handleChange = async (uploadFile, uploadFiles) => {
  // 文件信息
  let fileRaw = uploadFile.raw
  console.log(fileRaw)
  // 获取 文件的 MD5唯一标识码
  let fileMd5 = null
  try {
    fileMd5 = await getFileMd5(fileRaw)
  } catch(e) {
    console.error('[error]', e)
  }
  if(!fileMd5) return
  // 每片的大小为 5M 可调整
  const chunkSize = 5 * 1024 * 1024
  // 文件分片储存
  let chunkList = []
  function chunkPush(page = 1) {
    chunkList.push(fileRaw.slice((page - 1) * chunkSize, page * chunkSize))
    if(page * chunkSize < fileRaw.size) {
      chunkPush(page + 1)
    }
  }
  chunkPush()
  console.log(chunkList, 'chunkList----->>>')
  saveFileChunk(chunkList, fileMd5, fileRaw.name)
}
// 保存文件片段到后台
const saveFileChunk = async (chunkList, fileMd5, fileName) => {
  for(let i = 0; i < chunkList.length; i++) {
    let formData = new FormData()
    formData.append('chunk', i) // 当前片段的索引
    formData.append('chunkSize', 5 * 1024 * 1024) // 切片的文件分片大小 (就是以多少字节进行分片的,这里是5M)
    formData.append('chunks', chunkList.length) // 共有多少分片
    formData.append('file', chunkList[i]) // 当前分片的文件流
    formData.append('md5', fileMd5) // 整个文件的MD5唯一标识码,不是分片
    formData.append('name', fileName) // 文件的名称
    formData.append('size', chunkList[i].size) // 当前切片的大小(最后一片不一定是5M)
    const data = await saveFileChunk(formData)
    if(data && data.success) {
      console.log('保存成功')
    }
  }
}
</script>