You need to enable JavaScript to run this app. React中如何通过<input type="file">正确实现目录上传
优惠活动
大模型
产品
解决方案
定价
更多

React中如何通过<input type="file">正确实现目录上传

React中实现目录上传的正确方案

原实现失效的核心原因

  • 手动通过函数式ref执行setAttribute写入的属性,没有同步到组件的虚拟DOM props中,只要组件发生重渲染,React的DOM diff逻辑就会清除所有未在JSX中声明的DOM属性,导致目录上传的标记失效
  • 厂商前缀的目录上传属性存在浏览器兼容的命名识别规则,手动设置的属性如果大小写、命名格式不匹配,会直接被浏览器忽略
  • React 18严格模式下,函数式ref会被连续调用两次(挂载、卸载、重挂载),手动设置的属性很容易出现状态不稳定的问题

推荐的标准实现

不需要手动操作DOM,直接将目录上传属性作为JSX的声明式props写在input元素上即可,React会自动将这些属性同步到真实DOM:

  • 适配Chromium内核浏览器(Chrome、Edge等)的属性为webkitDirectory
  • 适配Firefox浏览器的属性为mozDirectory
  • 补充multiple属性,支持读取嵌套目录下的所有层级文件

示例代码:

function UploadDirectory() {
  return (
    <input
      type="file"
      webkitDirectory
      mozDirectory
      multiple
    />
  )
}

注意:这类带厂商前缀的属性在JSX中采用驼峰命名时,不需要额外赋值,只要属性存在就会被渲染到DOM上,和原生HTML中写<input type="file" webkitdirectory>的行为完全一致。

特殊场景兜底实现

如果遇到个别React版本对非标准属性的过滤问题,可以通过useRef配合useEffect,在组件完全挂载后再手动设置属性,避免被diff逻辑清除:

import { useRef, useEffect } from 'react';

function UploadDirectory() {
  const inputRef = useRef(null);

  useEffect(() => {
    const inputEl = inputRef.current;
    if (!inputEl) return;
    // 手动设置时使用原生的全小写属性名,保证浏览器正确识别
    inputEl.setAttribute('webkitdirectory', '');
    inputEl.setAttribute('mozdirectory', '');
  }, []);

  return <input type="file" ref={inputRef} multiple />;
}

注意事项

  • 目录上传属于非标准化浏览器API,目前Safari对该功能的支持并不完善,生产环境使用时需要做兼容性提示
  • 选中目录后读取到的每个File对象,都会携带webkitRelativePath字段,存储该文件在原选中目录下的相对路径,可用来还原本地目录的层级结构
  • 不要在JSX中把这类属性写成全小写的字符串键值对传参,比如{ webkitdirectory: '' },这类写法会被React识别为普通自定义属性,无法触发浏览器的目录选择逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.31 01:06:04