当前位置: 首页 > 知识库问答 >
问题:

javascript - 怎么通过文件上传的 files 列表还原 文件夹层级结构?

闻人嘉悦
2024-05-06

在做文件上传时选择文件夹,获取到 files 列表。但是不存在文件夹的目录层级。怎么样通过file的webkitRelativePath来遍历还原出文件夹结构。例如:
获取到的files变成数组后是:

const files = [  {    file: {      webkitRelativePath: ''    },    name: '测试文件.text'  },  {    file: {      webkitRelativePath: 'test/前端文件.PDF'    },    name: '前端文件.PDF'  },  {    file: {      webkitRelativePath: 'test/x/第一次上传.mp4'    },    name: '第一次上传.mp4'  },  {    file: {      webkitRelativePath: 'test/x/第二次上传.mp4'    },    name: '第二次上传.mp4'  }]

变成以后的结构:

const directory = [  {    file: {      webkitRelativePath: ''    },    Type: 'FILE',    name: '测试文件.text'  },  {    Type: 'DIR',    name: 'test',    subdirectory: [      {        file: {          webkitRelativePath: 'test/前端文件.PDF'        },        Type: 'FILE',        name: '前端文件.PDF'      },      {        Type: 'DIR',        name: 'x',        subdirectory: [          {            file: {              webkitRelativePath: 'test/x/第一次上传.mp4'            },            Type: 'FILE',            name: '第一次上传.mp4'          },          {            file: {              webkitRelativePath: 'test/x/第二次上传.mp4'            },            Type: 'FILE',            name: '第二次上传.mp4'          }        ]      }    ]  },]

非常感谢,已经卡在这里好久了,哪位大佬帮忙解决一下!

共有3个答案

屠昌胤
2024-05-06
const files = [ ... ]interface File {    file: { webkitRelativePath: string }    Type: 'FILE'    name: string}interface Directory {    Type: 'DIR'    name: string    subdirectory: FileOrDir[]}type FileOrDir = File | Directoryconst separator = '/',    dir = new Map<string, Directory>([        ['', { Type: 'DIR', name: '', subdirectory: [] }]    ])function getOrCreateDir(path: string): Directory {    if (dir.has(path)) return dir.get(path)!    const paths = path.split(separator),        last = paths.slice(-1)[0],        parent = getOrCreateDir(paths.slice(0, -1).join(separator))    if (last === '') return parent    let d = parent.subdirectory.find(d => d.name === last)    if (d?.Type === 'FILE') throw new TypeError(`${path} is a file`)    if (d) {        dir.set(path, d)        return d    }    d = { Type: 'DIR', name: last, subdirectory: [] }    parent.subdirectory.push(d)    dir.set(path, d)    return d}files.forEach(f =>    getOrCreateDir(        f.file.webkitRelativePath.split(separator).slice(0, -1).join(separator)    ).subdirectory.push({ ...f, Type: 'FILE' }))console.log(Deno.inspect(dir.get('')?.subdirectory, { depth: 10 }))
柯正谊
2024-05-06

文件得是 formdata, 这就限制了,你没办法传递,类似的办法是把名字改成全路径。

还有一种办法是把文件夹打包成 zip,这样就能保留目录了,缺点是服务端要解析。

反正左右都是要约定。你也可以直接约定一个数组,然后后端解析数组之后再重新挪一次位置我理解也可以

祁柏
2024-05-06

你可以通过递归的方式解决这个问题。首先,你需要按照 webkitRelativePath 对文件列表进行排序,确保父文件夹在子文件夹之前处理。然后,你可以创建一个函数来构建目录结构。以下是一个可能的实现:

const files = [  {    file: {      webkitRelativePath: ''    },    name: '测试文件.text'  },  {    file: {      webkitRelativePath: 'test/前端文件.PDF'    },    name: '前端文件.PDF'  },  {    file: {      webkitRelativePath: 'test/x/第一次上传.mp4'    },    name: '第一次上传.mp4'  },  {    file: {      webkitRelativePath: 'test/x/第二次上传.mp4'    },    name: '第二次上传.mp4'  }];// 根据webkitRelativePath排序files.sort((a, b) => a.file.webkitRelativePath.localeCompare(b.file.webkitRelativePath));function buildDirectoryStructure(files, currentPath = '') {  let structure = [];  let currentLevel = [];  for (let file of files) {    let filePath = file.file.webkitRelativePath;    let fileName = file.name;    if (filePath.startsWith(currentPath)) {      let relativePath = filePath.slice(currentPath.length);      let parts = relativePath.split('/');      let parent = currentLevel;      for (let i = 0; i < parts.length - 1; i++) {        let part = parts[i];        let child = parent.find(item => item.name === part && item.Type === 'DIR');        if (!child) {          child = { Type: 'DIR', name: part, subdirectory: [] };          parent.push(child);        }        parent = child.subdirectory;      }      let lastPart = parts[parts.length - 1];      let fileItem = { Type: 'FILE', file: file.file, name: fileName };      parent.push(fileItem);    }  }  structure.push({ Type: 'DIR', name: currentPath.split('/').pop(), subdirectory: currentLevel });  return structure;}const directory = buildDirectoryStructure(files);console.log(directory);

这个 buildDirectoryStructure 函数会递归地遍历文件列表,根据 webkitRelativePath 构建目录结构。注意,这个函数假设 webkitRelativePath 是相对于当前选择的文件夹的。如果 webkitRelativePath 是相对于文件系统的根目录,你可能需要稍微修改这个函数以适应你的需求。

这个实现也假设了 webkitRelativePath 是以 / 分隔的,并且每个文件夹名不包含 /。如果这些假设不成立,你可能需要修改这个函数以适应你的实际情况。

 类似资料:
  • 问题内容: 选择图像,doc或pdf后,我想将它们通过okhttp3。如何进行此操作? 并在okhttp 3中 显示的错误是 谢谢。 问题答案: 所以我自己回答这个问题。 因此,我首先将输出流打开到一个临时文件。 扩展名取决于mime类型。您可以通过以下方式找到mime类型 现在从文件读取并将其内容写入临时文件 现在写入文件 最后 成功之后的最后

  • 问题内容: 我使用2个文件index.js,upload.php尝试通过ajax上传文件(img),如果成功追加到div 。 但是它不起作用,有几个问题,下面我的代码有什么建议吗? 谢谢。 upload.php 1. 还需要添加吗? 2. 并检查$ _FILES的大小或tmp_name是否仍使用? index.js 3.这几行是对的吗? 4.我错过或错了什么吗? 问题答案: 在其构造函数中接受一个

  • 问题内容: 我正在尝试在PMA中还原数据库,但只能访问frm和ibd文件,而不能访问我了解您需要的ib_log文件。 我知道我可能无法恢复数据库数据,但是是否可以从frm文件恢复表的结构? 问题答案: 我仅从和文件中还原了该表。 获取SQL查询以创建表 如果您已经知道表的架构,则可以跳过此步骤。 首先,安装MySQL Utilities。然后,您可以在命令提示符(cmd)中使用命令。 其次,使用以

  • 我正在寻找一种方法来获取zip文件中的文件列表。我创建了一个方法来获取目录中的文件列表,但我也在寻找一种方法来获取zip文件中的文件,而不是只显示zip文件。 以下是我的方法:

  • 问题内容: 我想使用将文件(特别是图像)上传到REST Server 。我已经导入/添加了构建路径和。而且我在堆栈跟踪中收到以下错误。 这有效吗? HTTP POST代码 堆栈跟踪 问题答案: 您似乎缺少依赖项。 我有,,并用和在我的类路径罐子。 我也使用而不是使用header属性。 查看Internet媒体类型以了解更多详细信息

  • 我有一个问题,通过我的php网站上传一个mp3文件。它允许我加载2MB以下的所有内容,但没有超过。它以前工作过 托管提供商还增加了fastcgi超时限制。htaccess文件,并添加以下内容:php\u value max\u execution\u time 300, 我们还增加了fastcgi超时限制,并添加了一个。htaccess文件:php\u值上传\u最大\u文件大小20M php\u值