You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React实现带圆形进度展示的文件上传并将文件存入组件state

自定义Antd Upload实现带圆形进度的文件上传功能

你可以基于Antd的Upload组件做二次改造,关闭默认上传逻辑,自定义上传行为和列表渲染样式即可实现需求,具体实现方案如下:

实现思路

  • 关闭Upload组件的自动上传,通过beforeUpload钩子获取文件对象,将file.originFileObj存入组件state
  • 自定义上传请求逻辑,通过XMLHttpRequest监听上传进度事件,实时更新进度百分比到state
  • 重写Upload的itemRender属性,自定义上传列表的渲染逻辑,展示圆形进度条、文件大小、上传百分比

核心代码示例

import { Upload, Progress, Button } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { useState } from 'react';

const CustomUpload = () => {
  // 存储文件列表和对应上传进度
  const [fileList, setFileList] = useState([]);
  const [uploadProgress, setUploadProgress] = useState({});

  // 上传前钩子,获取文件存入state,阻止默认上传
  const beforeUpload = (file) => {
    setFileList(prev => [...prev, file]);
    // 触发自定义上传逻辑
    customUpload(file);
    // 返回false阻止组件默认上传行为
    return false;
  };

  // 自定义上传逻辑
  const customUpload = (file) => {
    const formData = new FormData();
    // 从file对象中取originFileObj存入formData
    formData.append('file', file.originFileObj);
    const xhr = new XMLHttpRequest();

    // 监听上传进度
    xhr.upload.addEventListener('progress', (e) => {
      if (e.lengthComputable) {
        const percent = Math.round((e.loaded / e.total) * 100);
        setUploadProgress(prev => ({
          ...prev,
          [file.uid]: percent
        }));
      }
    });

    // 此处替换为你的实际上传接口地址
    xhr.open('POST', '/your/upload/api', true);
    xhr.send(formData);

    xhr.onload = () => {
      // 可根据接口返回结果补充上传成功/失败的状态处理逻辑
    };
  };

  // 自定义上传项渲染
  const itemRender = (originNode, file) => {
    const progress = uploadProgress[file.uid] || 0;
    // 文件大小格式化方法
    const formatFileSize = (size) => {
      if (size < 1024) return size + ' B';
      if (size < 1024 * 1024) return (size / 1024).toFixed(2) + ' KB';
      return (size / 1024 / 1024).toFixed(2) + ' MB';
    };

    return (
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '8px 0' }}>
        <span>{file.name}</span>
        <span>{formatFileSize(file.size)}</span>
        {progress < 100 ? (
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <Progress type="circle" size={30} percent={progress} />
            <span>{progress}%</span>
          </div>
        ) : <span>上传完成</span>}
      </div>
    );
  };

  return (
    <Upload
      fileList={fileList}
      beforeUpload={beforeUpload}
      itemRender={itemRender}
    >
      <Button icon={<UploadOutlined />}>选择文件</Button>
    </Upload>
  );
};

export default CustomUpload;

效果说明

  • 上传前展示选择文件按钮和已选文件的名称、大小,匹配上传前的展示需求
  • 上传过程中实时渲染圆形进度条和上传百分比,符合上传中的展示要求
  • 所有选中的文件都可以通过file.originFileObj从fileList状态中直接获取,满足文件存入state的需求

内容的提问来源于stack exchange,提问作者Abdul Wahab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 09:36:03