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

React实现深度嵌套文件夹上传时数组扁平化异常问题

问题分析

你的问题出在嵌套Promise解析后生成了多层嵌套数组,而Array.flat()默认只扁平化一层,深层的嵌套数组无法被展开。

看你的traverseDirectory函数:处理子目录时,它返回的Promise最终会解析为Promise.all(fileList)的结果——也就是一个包含File对象和子目录Promise解析结果的数组。当存在多层子目录时,这个结构会变成[File, [File, [File]]]这样的嵌套形式,仅用flat()只能展开最外层的数组,深层的嵌套数组依然保留。

解决方案

这里提供两种可行的修复方式:

方式一:使用flat(Infinity)彻底扁平化数组

这是最简单的修改,只需要把setFiles(files.flat())改成setFiles(files.flat(Infinity)),Infinity参数会让数组不管嵌套多少层都被完全扁平化为一维数组:

Promise.all(fileList).then((files) => {
  console.log(files, files.flat(Infinity))
  setFiles(files.flat(Infinity));
});

方式二:重构traverseDirectory,直接收集所有File对象

如果不想依赖flat(Infinity),可以重构遍历逻辑,让traverseDirectory直接返回包含所有File对象的一维数组Promise,从根源避免嵌套结构。用async/await能让代码逻辑更直观:

const [files, setFiles] = useState([]);

const handleDropFile = async (event) => {
  event.preventDefault();
  const items = event.dataTransfer.items;
  const fileList = [];
  
  for (let i = 0; i < items.length; i++) {
    const entry = items[i].webkitGetAsEntry();
    if (entry.isFile) {
      fileList.push(entry.file());
    } else if (entry.isDirectory) {
      fileList.push(...await traverseDirectory(entry, entry.name + "/"));
    }
  }
  
  const allFiles = await Promise.all(fileList);
  setFiles(allFiles);
};

const traverseDirectory = async (directory, currentPath) => {
  const reader = directory.createReader();
  const fileList = [];
  
  const readEntries = async () => {
    const entries = await new Promise(resolve => reader.readEntries(resolve));
    for (const entry of entries) {
      if (entry.isFile) {
        const file = await entry.file();
        const modifiedFile = new File(
          [file],
          currentPath + file.name,
          { type: file.type }
        );
        fileList.push(modifiedFile);
      } else if (entry.isDirectory) {
        const subFiles = await traverseDirectory(entry, `${currentPath}/${entry.name}`);
        fileList.push(...subFiles);
      }
    }
    if (entries.length > 0) {
      await readEntries();
    }
  };
  
  await readEntries();
  return fileList;
};

重构后的优势:

  • 用async/await替代嵌套Promise,代码逻辑更易读
  • traverseDirectory直接返回一维的File对象数组,不需要后续扁平化处理
  • 补上了原始代码中未调用readEntries的隐性问题,确保目录遍历能正常执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 13:28:17