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

寻求支持大文件量选择的React文件选择组件

React 目录选择组件(仅获取文件)

下面是完全符合你需求的组件实现,解决了Antd Upload多次触发回调、rpldy无法获取webkitRelativePath的问题:

import { useRef } from 'react';

const DirectoryFilePicker = ({ onFilesSelected }) => {
  const fileInputRef = useRef(null);

  // 打开文件选择对话框
  const handleOpenPicker = () => {
    fileInputRef.current?.click();
  };

  // 处理文件选择对话框的change事件
  const handleFileInputChange = (e) => {
    const files = Array.from(e.target.files);
    if (files.length > 0) {
      onFilesSelected(files);
      // 重置input,否则重复选同一目录不会触发change
      e.target.value = '';
    }
  };

  // 拖拽事件处理:阻止默认行为,避免浏览器跳转
  const handleDragEvent = (e) => {
    e.preventDefault();
    e.stopPropagation();
  };

  // 处理拖拽放下事件
  const handleDrop = (e) => {
    handleDragEvent(e);
    const files = Array.from(e.dataTransfer.files);
    if (files.length > 0) {
      onFilesSelected(files);
    }
  };

  return (
    <div
      onClick={handleOpenPicker}
      onDragEnter={handleDragEvent}
      onDragOver={handleDragEvent}
      onDrop={handleDrop}
      style={{
        border: '2px dashed #ccc',
        borderRadius: '8px',
        padding: '40px',
        textAlign: 'center',
        cursor: 'pointer',
        transition: 'border-color 0.3s',
      }}
      onMouseEnter={(e) => e.currentTarget.style.borderColor = '#1890ff'}
      onMouseLeave={(e) => e.currentTarget.style.borderColor = '#ccc'}
    >
      <input
        ref={fileInputRef}
        type="file"
        webkitdirectory
        directory
        multiple
        style={{ display: 'none' }}
        onChange={handleFileInputChange}
      />
      <p>点击或拖拽目录到此处</p>
      <p style={{ fontSize: '14px', color: '#666', marginTop: '8px' }}>选择后将获取所有文件的相对路径</p>
    </div>
  );
};

export default DirectoryFilePicker;

组件使用示例

import DirectoryFilePicker from './DirectoryFilePicker';

function App() {
  const handleFilesReceived = (files) => {
    // 这里一次性拿到所有文件,仅触发一次状态更新
    console.log('所有文件:', files);
    // 可以提取webkitRelativePath用于预览
    const filePaths = files.map(file => file.webkitRelativePath);
    console.log('文件相对路径列表:', filePaths);
  };

  return (
    <div style={{ padding: '20px' }}>
      <h2>目录文件选择器</h2>
      <DirectoryFilePicker onFilesSelected={handleFilesReceived} />
    </div>
  );
}

关键特性说明

  • 仅允许选目录:通过原生input的webkitdirectory和directory属性实现,浏览器会强制弹出目录选择对话框,无法选择单个文件
  • 拖拽+对话框双支持:既可以点击打开选择框,也可以直接拖拽目录到组件区域
  • 单次回调触发:不管选中多少文件,都会一次性将所有文件转为数组后调用onFilesSelected,避免多次重渲染
  • 保留webkitRelativePath:每个File对象都原生携带该属性,直接就能获取文件在目录中的相对路径,无需额外处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 09:25:24