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

仅用React与Material UI能否为input标签实现图片上传加载条?

问题解答

核心结论

原生<input type="file">没有内置的上传进度监听能力。它的onChange事件仅在用户完成文件选择时触发,此时文件还处于本地状态,并未开始向服务器传输,所以无法通过input自身的事件获取上传进度。

你的代码为什么没生效

你尝试的写法里,setFileUploading(true)和setFileUploading(false)是同步执行的:

onChange={(event) => {
  setFileUploading(true)
  handleUploadChange(event)
  setFileUploading(false)
}}

React的状态更新是异步批量处理的,这两次状态变更会被合并,最终fileUploading始终是false,进度指示器自然不会渲染。

正确实现方式

要显示上传进度,必须手动通过XMLHttpRequest或Fetch API处理文件上传,利用它们的进度监听事件更新状态。以下是React + Material UI的完整示例:

import { useState } from 'react';
import { Button, LinearProgress, Typography } from '@mui/material';

const FileUploader = () => {
  const [isUploading, setIsUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState(0);

  const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) return;

    setIsUploading(true);
    setUploadProgress(0);

    const formData = new FormData();
    formData.append('image', file);

    const xhr = new XMLHttpRequest();
    xhr.open('POST', '/your-upload-api-endpoint'); // 替换为你的实际上传接口

    // 监听上传进度
    xhr.upload.onprogress = (e) => {
      if (e.lengthComputable) {
        const progress = Math.round((e.loaded / e.total) * 100);
        setUploadProgress(progress);
      }
    };

    // 上传完成/失败处理
    xhr.onload = () => {
      if (xhr.status === 200) {
        console.log('上传成功');
        // 可添加上传成功后的逻辑,比如重置input、显示成功提示等
      } else {
        console.error('上传失败');
      }
      setIsUploading(false);
    };

    xhr.onerror = () => {
      console.error('上传请求出错');
      setIsUploading(false);
    };

    xhr.send(formData);
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'flex-start' }}>
      <Button variant="contained" component="label" disabled={isUploading}>
        {isUploading ? '上传中...' : '选择图片'}
        <input
          type="file"
          hidden
          accept="image/*"
          onChange={handleFileUpload}
          disabled={isUploading}
        />
      </Button>

      {isUploading && (
        <div style={{ width: '100%', maxWidth: 400 }}>
          <Typography variant="body2" gutterBottom>
            上传进度: {uploadProgress}%
          </Typography>
          <LinearProgress variant="determinate" value={uploadProgress} />
          {/* 若偏好圆形进度条,可替换为:<CircularProgress variant="determinate" value={uploadProgress} /> */}
        </div>
      )}
    </div>
  );
};

export default FileUploader;

关键说明

  • 利用XMLHttpRequest.upload.onprogress事件监听上传进度,该事件会在文件传输过程中持续触发,通过e.loaded(已传输字节数)和e.total(总字节数)计算进度百分比。
  • 上传开始时设置isUploading为true并重置进度;上传完成(成功/失败)后再将isUploading设为false。
  • 禁用上传按钮和input,避免用户重复触发上传操作。

如果偏好使用Fetch API,可结合ReadableStream实现进度监听,但代码复杂度更高,上述XMLHttpRequest方案更直观易用。

内容的提问来源于stack exchange,提问作者engineer-x

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 13:01:03