说到拖拽本地文件到浏览器中,基本也就是用来上传文件。首先,监听元素的onDragEnter和onDragLeave事件,捕获鼠标拖拽本地文件(或者文件夹)进入或离开。监听onDrop事件,即捕获鼠标放下被拖拽的文件(或者文件夹)。
对于onDragXXX事件,这里就不展开了,下面主要分享的是,如何从onDrop事件的event.dataTransfer获取被拖拽的所有文件(包括文件夹下的文件)。虽然,dataTransfer中有一个“files”成员属性,但不幸的是,兼容性不好,很多浏览器里为空值。所以,只能使用其中的“items”。
/** 遍历文件/文件夹 */
export function readTransferFiles(
items: DataTransferItemList,
completeCallback: (fileList: FileItem[]) => void,
) {
let fileCount = items.length;
let fileList: FileItem[] = [];
for (let item of items) {
if (item.kind === 'file') {
const entry = item.webkitGetAsEntry();
if (entry) {
readEntry(entry);
continue;
}
}
decrCount();
}
function decrCount() {
if (--fileCount === 0) {
completeCallback(fileList);
}
}
function readEntry(entry: FileSystemEntry) {
if (entry.isFile) {
(entry as FileSystemFileEntry).file((f) => {
fileList.push({
path: entry.fullPath.substring(1),
file: f,
});
decrCount();
});
} else if (entry.isDirectory) {
const dir = (entry as FileSystemDirectoryEntry).createReader();
dir.readEntries((entries) => {
if (entries.length > 0) {
fileCount += entries.length;
for (const e of entries) {
// 子目录递归
readEntry(e);
}
} else {
// 空目录
fileList.push({
path: entry.fullPath.substring(1),
});
}
decrCount();
});
} else {
decrCount();
}
}
}
参数completeCallback是遍历完毕之后的回调函数,也可以改成异步的Promise方式。