我还没有看到任何这样做的例子。 API规范中不允许这样做吗?
我正在寻找一种简单的拖放解决方案来上传整个照片文件夹树。
原文由 michael 发布,翻译遵循 CC BY-SA 4.0 许可协议
我还没有看到任何这样做的例子。 API规范中不允许这样做吗?
我正在寻找一种简单的拖放解决方案来上传整个照片文件夹树。
原文由 michael 发布,翻译遵循 CC BY-SA 4.0 许可协议
不幸的是,现有的答案都不是完全正确的,因为 readEntries
不一定会返回给定目录的 所有(文件或目录)条目。这是 API 规范的一部分(请参阅下面的文档部分)。
要真正获取 所有 文件,我们需要重复调用 readEntries
(对于我们遇到的每个目录),直到它返回一个空数组。如果我们不这样做,我们将错过目录中的一些文件/子目录,例如在 Chrome 中, readEntries
一次最多只返回 100 个条目。
使用 Promises ( await
/ async
) 来更清楚地展示 readEntries
的正确用法,以及 BFS-first 遍历它(因为 BFS 是异步的)目录结构:
// Drop handler function to get all files
async function getAllFileEntries(dataTransferItemList) {
let fileEntries = [];
// Use BFS to traverse entire directory/file structure
let queue = [];
// Unfortunately dataTransferItemList is not iterable i.e. no forEach
for (let i = 0; i < dataTransferItemList.length; i++) {
// Note webkitGetAsEntry a non-standard feature and may change
// Usage is necessary for handling directories
queue.push(dataTransferItemList[i].webkitGetAsEntry());
}
while (queue.length > 0) {
let entry = queue.shift();
if (entry.isFile) {
fileEntries.push(entry);
} else if (entry.isDirectory) {
queue.push(...await readAllDirectoryEntries(entry.createReader()));
}
}
return fileEntries;
}
// Get all the entries (files or sub-directories) in a directory
// by calling readEntries until it returns empty array
async function readAllDirectoryEntries(directoryReader) {
let entries = [];
let readEntries = await readEntriesPromise(directoryReader);
while (readEntries.length > 0) {
entries.push(...readEntries);
readEntries = await readEntriesPromise(directoryReader);
}
return entries;
}
// Wrap readEntries in a promise to make working with readEntries easier
// readEntries will return only some of the entries in a directory
// e.g. Chrome returns at most 100 entries at a time
async function readEntriesPromise(directoryReader) {
try {
return await new Promise((resolve, reject) => {
directoryReader.readEntries(resolve, reject);
});
} catch (err) {
console.log(err);
}
}
Codepen 上的完整工作示例: https ://codepen.io/pen/QWmvxwV
FWIW 我之所以选择这个,是因为在使用接受的答案时,我没有在包含 40,000 个文件的目录(许多目录包含超过 100 个文件/子目录)中取回我期望的所有文件。
文档:
此行为记录在 FileSystemDirectoryReader 中。摘录重点补充:
读取条目()
返回一个数组,其中包含 一定数量的 _目录条目_。数组中的每一项都是一个基于 FileSystemEntry 的对象——通常是 FileSystemFileEntry 或 FileSystemDirectoryEntry。
但公平地说,MDN 文档可以在其他部分更清楚地说明这一点。 readEntries() 文档简单地指出:
readEntries() 方法检索正在读取的目录中的目录条目,并将它们以数组形式传递给提供的回调函数
唯一需要多次调用的提及/提示是在 successCallback 参数的描述中:
如果没有剩余文件,或者您已经在此 FileSystemDirectoryReader 上调用了 readEntries(),则该数组为空。
可以说 API 也可以更直观。
还值得注意的是 DataTransferItem.webkitGetAsEntry() 是一个非标准功能,可能会更改,例如重命名 getAsEntry()
。它的使用对于处理嵌套在目录中的上传文件是必要的。
有关的:
readEntries
将返回最多 100 个目录条目(从 Chrome 64 开始验证)。readEntries
的正确用法(尽管没有代码)。readEntries
。他还指出,Firefox 会返回一个目录中的所有条目(与 Chrome 不同),但我们不能依赖给定的规范。原文由 xlm 发布,翻译遵循 CC BY-SA 4.0 许可协议
10 回答11.2k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.8k 阅读✓ 已解决
3 回答2.3k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
现在可以,感谢 Chrome >= 21。
更多信息: https ://protonet.info/blog/html5-experiment-drag-drop-of-folders/