仅用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
相关产品推荐
相关产品推荐

