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

如何使用react-dropzone-uploader实现文件夹上传功能?

解决react-dropzone-uploader文件夹上传问题

你的代码无法正常工作主要有几个关键问题,以下是针对性的修正方案:

1. 修正文件夹选择属性

原代码中directory=""和webkitdirectory=""的写法错误,React中布尔属性需要传递true值而非空字符串。同时无需手动设置type="file"和multiple={true},组件会自动处理这些配置。

2. 自定义getFilesFromEvent处理文件夹文件

默认的getFilesFromEvent不会递归读取文件夹内的文件,需要自己实现递归遍历逻辑来获取所有子文件:

const getFilesFromEvent = async (event) => {
  const files = [];
  // 递归遍历文件夹结构
  const traverseFileTree = async (item, path = '') => {
    if (item.isFile) {
      const file = await item.file();
      // 给文件添加相对路径(可选,用于保留文件夹结构)
      file.relativePath = `${path}${item.name}`;
      files.push(file);
    } else if (item.isDirectory) {
      const directoryReader = item.createReader();
      const entries = await new Promise((resolve, reject) => {
        directoryReader.readEntries(resolve, reject);
      });
      for (const entry of entries) {
        await traverseFileTree(entry, `${path}${item.name}/`);
      }
    }
  };

  // 处理拖拽事件
  if (event.dataTransfer && event.dataTransfer.items) {
    for (const item of event.dataTransfer.items) {
      if (item.kind === 'file') {
        const entry = item.webkitGetAsEntry();
        if (entry) {
          await traverseFileTree(entry);
        } else {
          files.push(item.getAsFile());
        }
      }
    }
  } 
  // 处理文件选择框事件
  else if (event.target.files) {
    for (const file of event.target.files) {
      // 浏览器自动为文件夹内文件添加webkitRelativePath属性
      file.relativePath = file.webkitRelativePath || file.name;
      files.push(file);
    }
  }
  return files;
};

3. 修正selectFileInput配置

确保文件选择输入框支持文件夹选择:

const selectFileInput = ({ accept, onFiles, disabled }) => {
  return (
    <input
      type="file"
      directory
      webkitdirectory
      multiple
      disabled={disabled}
      onChange={(e) => {
        getFilesFromEvent(e).then(onFiles);
      }}
    />
  );
};

完整修正后的组件代码

import Dropzone from 'react-dropzone-uploader';
import 'react-dropzone-uploader/dist/styles.css';

// 预览组件示例(可自定义样式)
const Preview = ({ file }) => {
  return (
    <div style={{ padding: '8px', borderBottom: '1px solid #eee' }}>
      <span>{file.name}</span>
      <span style={{ marginLeft: '8px', color: '#666' }}>
        ({file.relativePath || '根目录'})
      </span>
    </div>
  );
};

// 上传参数配置示例(替换为你的实际接口)
const FilesMeta = () => {
  return { url: '/your-upload-api-endpoint' };
};

const FolderUploadDropzone = () => {
  return (
    <Dropzone
      getUploadParams={FilesMeta}
      getFilesFromEvent={getFilesFromEvent}
      PreviewComponent={Preview}
      selectFileInput={selectFileInput}
      directory={true}
      webkitdirectory={true}
      inputContent={
        <div>
          <p className="dropText">拖拽或选择文件夹</p>
        </div>
      }
    />
  );
};

export default FolderUploadDropzone;

关键说明

  • 递归遍历函数traverseFileTree会处理拖拽的文件夹,读取所有子文件并保留相对路径信息
  • 对于文件选择框触发的事件,浏览器会自动为文件夹内的文件添加webkitRelativePath属性,可直接复用
  • 若需要保留文件夹结构上传,需确保你的后端接口支持接收带相对路径的文件信息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 16:01:00