准备

借助antdUpload组件实现批量上传

需要接口支持

接口配置

/** 批量上传图片 */
export function batchUploadImages(data: FormData, config?: AxiosRequestConfig) {
  return request<API.BasicResponse>('api地址', {
    method: 'post',
    data,
    config,
  })
}

axios配置(基于UMI)

// 请求拦截器
requestInterceptors: [
  (url: any, options: any) => {
    
    // options相当于
    //   {
    //     method: 'post',
    //     data,
    //     config,
    //   }
    
    return {
      url,
      options: {
        ...options,
        // 上传进度条和其他配置
        ...options.config,
        headers: {
          Authorization: getToken(),
        },
        params: {
          ...options.params,
        },
      },
    }
  },
]

Upload组件配置

<Upload
  name="files[]" // 由后端决定
  disabled={uploadProgress.isUploading}
  multiple
  showUploadList={false}
  fileList={uploadFileList}
  customRequest={() => {}} // 阻止默认上传行为
  headers={{
    Authorization: getToken(),
  }}
  onChange={handleUploadProgress}
  >
  <Button icon={<UploadOutlined />}>Upload</Button>
</Upload>

handleUploadProgress

// 图片上传总数
const handleUploadProgress = (info: UploadChangeParam) => {
  setUploadFileList(info.fileList)
  setUploadProgress((prevState) => {
    return {
      ...prevState,
      current: 0,
      total: info.fileList.length,
      // 将 fileList 分割成多个批次
      batches: Math.ceil(info.fileList.length / perBatch),
      percent: 0,
    }
  })
}

handleUploadPicture

const [perBatch, setPerBatch] = useState<number>(20)
// 修改分片大小
const handlePerBatchChange = (value: number | null) => {
  if (!value) return
  setPerBatch(value)
  setUploadProgress((prevState) => {
    return {
      ...prevState,
      batches: Math.ceil(prevState.total / value),
    }
  })
}

// 图片批量上传
const handleUploadPicture = async (fileList: UploadFile[]) => {
  setUploadProgress((prevState) => {
    return {
      ...prevState,
      isUploading: true,
    }
  })
  // 循环上传每个批次的文件
  for (let i = 0; i < uploadProgress.batches; i++) {
    const start = i * perBatch
    const end = Math.min((i + 1) * perBatch, fileList.length)
    const filesToUpload = fileList.slice(start, end)
    
    const formData = new FormData()
    filesToUpload.forEach((file) => {
      formData.append('files[]', file.originFileObj!)
    })
    
    // 使用 await 等待当前批次的文件上传完成
    try {
      const res = await batchUploadImages(formData, {
        onUploadProgress,
        timeout: 900000,
      })
      if (res.code !== 200) {
        message
          .error({
            duration: 10,
            content: res.msg || formatMessage({ id: 'intl.upload.error' }),
          })
          .then()
        handleUploadStop()
        break
      }
      // 等待1.5秒,确保服务器端处理完成
      await new Promise((resolve) => {
        setTimeout(resolve, 1500)
      })
    } catch (error: any) {
      handleUploadStop()
      message
        .error({
          duration: 10,
          content:
            error.message || formatMessage({ id: 'intl.upload.error' }),
        })
        .then()
      break
    }
    setUploadProgress((prevState) => {
      return {
        ...prevState,
        current: prevState.current + 1,
      }
    })
    if (end === fileList.length) {
      setUploadProgress((prevState) => {
        return {
          ...prevState,
          isUploading: false,
        }
      })
      setUploadFileList([])
    }
  }
}

onUploadProgress

这个方法会传给axios的config中, 显示当前上传进度

// 图片批量上传的进度条
const onUploadProgress = (progressEvent: any) => {
  const { loaded, total } = progressEvent
  let percent = Math.floor((loaded * 100) / total)
  if (percent >= 100) {
    setUploadFileList([])
  }
  setUploadProgress((prevState) => {
    return {
      ...prevState,
      percent,
    }
  })
}

上传速度

可以根据onUploadProgressloadedtotal计算出上传速度

Last Updated:
Contributors: huangdingxin