前端大文件上传方案——分片上传

这里我们用的的组件是antd-vue 的 upload 组件

upload 组件的自定义上传文件的方法

 async customRequest(info) {
      const buffer = await this.fileToBuffer(info.file) // 将文件对象转换成array buffer 格式
      // 可以将文件按固定大小或者固定数量的方式进行切片,这里我们选择采用固定文件大小的方式,固定大小为2M
      const chunkSize = 2 * 1024 * 1024 // 固定大小2M
      const chunkList = [] // 保存所有切片的数组
      const chunkListLength = Math.ceil(info.file.size / chunkSize) // 计算总共多个切片
      const suffix = /\.([0-9A-z]+)$/.exec(info.file.name)[1] // 文件后缀名

      // 根据文件内容生成 hash 值
      const spark = new SparKMD5.ArrayBuffer()
      spark.append(buffer)
      const hash = spark.end()
      this.hash = hash
      // 生成切片,这里后端要求传递的参数为字节数据块(chunk)和每个数据块的文件名(fileName)
      let curChunk = 0 // 切片时的初始位置
      for (let i = 0; i < chunkListLength; i++) {
        const item = {
          chunk: info.file.slice(curChunk, curChunk + chunkSize),
          fileName: `${hash}_${i}.${suffix}`, // 文件名规则按照 hash_1. 命名
        }
        curChunk += chunkSize
        chunkList.push(item)
      }
      this.chunkList = chunkList
      this.sendRequest()
    },

// 将文件对象转换成array buffer格式

 fileToBuffer(file) {
      return new Promise((resolve, reject) => {
        const fr = new FileReader()
        fr.onload = (e) => {
          resolve(e.target.result)
        }
        fr.readAsArrayBuffer(file)
        fr.onerror = () => {
          reject(new Error('转换文件格式发生错误'))
        }
      })
    },

// 发送请求

sendRequest() {
      const requestList = [] //  请求集合
      this.chunkList.forEach((item, index) => {
        const fn = () => {
          const { id } = this.$route.query
          const formData = new FormData()
          formData.append('file', item.chunk)
          formData.append('fileName', item.fileName)
          const obj = {
            url: '/pm/project/management/file/upload',
            requestData: formData,
          }
          submitData(obj).then((res) => {
            if (res.code === 0) {
      
              // this.$message.success('上传成功')
            }
          })
        }
        requestList.push(fn)
      })
      let i = 0 // 记录发送的请求个数
      const send = async () => {
        // if ('暂停') return
        if (i >= requestList.length) {
          // 所有的chunk发送完毕,向后端发送合并文件的请求,告诉后端合并文件
          this.sendComplete()
          return
        }
        await requestList[i]()
        i++
        send()
      }
      send() // 发送请求
    },

你可能感兴趣的:(前端,javascript)