Skip to content

文件上传时需注意清空 input 的 value 值 ​

问题描述 ​

在 React 中使用 input type="file" 进行文件上传时,如果用户重复上传同一个文件,会发现第二次上传无法触发 onChange 事件。这是因为 input 的 value 值没有被清空,导致 React 认为文件没有发生变化。

解决方案 ​

在触发文件选择框之前,需要先清空 input 的 value 值。

代码示例 ​

jsx
// 文件输入框的引用
const fileInputRef = useRef(null);

// 处理文件选择变化
const handleFileInputChange = (e) => {
  const fileList = [...e.target.files];
  handlerFiles(fileList); // 处理选中的文件
};

// 处理上传按钮点击
const handleUploadIconClick = () => {
  // 重要:清空 input 的 value,确保相同文件可以重复上传
  fileInputRef.current.value = '';
  fileInputRef.current.click();
};

// JSX 部分
<input
  ref={fileInputRef}
  type="file"
  multiple
  style={{ display: "none" }}
  onChange={handleFileInputChange}
  accept=".jpg, .jpeg, .png, .obj, .fbx, .gltf, .glb, .dae, .ply, .stl, .heic"
/>

注意事项 ​

  1. 必须在触发文件选择前清空 input 的 value
  2. 使用 ref 来获取 input 元素的引用
  3. 可以通过 style={ display: "none" } 隐藏原生文件选择框
  4. multiple 属性允许选择多个文件
  5. accept 属性用于限制可选择的文件类型

最佳实践 ​

  • 为了更好的用户体验,建议添加文件类型验证
  • 可以添加文件大小限制
  • 建议添加上传进度提示
  • 处理上传错误的情况

扩展示例 ​

jsx
const handleFileInputChange = (e) => {
  const fileList = [...e.target.files];
  
  // 文件验证
  const validFiles = fileList.filter(file => {
    // 文件大小限制(例如:10MB)
    const isValidSize = file.size <= 10 * 1024 * 1024;
    
    // 文件类型验证
    const validTypes = ['image/jpeg', 'image/png'];
    const isValidType = validTypes.includes(file.type);
    
    return isValidSize && isValidType;
  });

  if (validFiles.length !== fileList.length) {
    alert('某些文件不符合要求,已被过滤');
  }

  handlerFiles(validFiles);
};

这样的文件上传处理方式更加健壮和用户友好。记住,清空 input 的 value 值是处理文件重复上传的关键所在。