前端大文件切片上传

230 阅读1分钟

前端大文件切片上传

基本步骤

  1. 上传文件;
  2. 文件按需切割为不等分;
  3. 逐步切片请求;
  • 创建FormData对象,为每一片数据添加上描述信息和添加序号;
  • 发起请求(返回promise);
  1. 全部上传成功后,发起合并文件请求。

处理逻辑部分

    import { getInfo, postInfo, uploadSlice, uploadEnd } from '../apis/index'
    
    // 2.文件按需切割为不等分:默认0.5M分一片
    const createThunck = (file, size = 1024 * 1024 * 0.5) => {
      const result = [] //文件切片之后的数组
      let cur = 0 //当前大小(位置)

      while (cur < file.size) {
        result.push({
          sliceFile: file.slice(cur, cur + size)
        })
        cur += size
      }

      return result
    }

    // 1.上传文件
    //选中文件后,e.target.files的值,当然,这个值是数组,我们需要他的第一个
    //注意的就是使用 data 传递了一个参数,参数类型是 FromData。
    const uploadFile = async (e) => {
      const files = e.target.files
      const fileList = createThunck(files?.[0], 1000)
      const uuid = crypto.randomUUID()
      
      // 3.逐步切片请求:切片请求
      const uploadList = fileList.map((item, index) => {
        const formData = new FormData() //定义上传数据
        formData.append('fileChunk', item.sliceFile) //切片块数据
        formData.append('fileChunkName', uuid + '@' + index) //切片块名称
        formData.append('fileName', uuid + '@' + files[0].name) //文件名
        return uploadSlice(formData)
      })
      
      //4.全部上传成功后,发起合并文件请求:所有切片上传成功后,发起文件合并请求
      Promise.all(uploadList).then(res => {
        console.log('上传成功');
        uploadEnd({
          fileList: files[0].name, //文件名
          extname: files[0].name.split('.').slice(-1)[0] //文件后缀名
        }).then(res => console.log(res.data))
      })
      .catch(err => {
        console.log(err);
      })
    }

请求方法

import axios from "axios";

const BASE_URL = '/api'

export const uploadSlice = (file) => {
  return axios({
    url: '/upload_slice',
    baseURL: BASE_URL,
    method: 'post',
    data: file,
    onUploadProgress(progressEvent) {
      let complete = (((progressEvent.loaded / progressEvent.total) * 100) | 0) + '%';
      // console.log('上传 ' + complete);
    }
  })
}
export const uploadEnd = (data) => {
  return axios({
    url: '/upload_end',
    baseURL: BASE_URL,
    method: 'post',
    data,
    timeout: 5000,
  })
}