上传文件夹

123 阅读1分钟

原理

input元素的webkitdirectory属性

caniuse

Code

// 扫描获取文件列表
async function scanFileSystemEntry(entry: FileSystemEntry): Promise<File[]> {
    if (!entry) return [];

    const result: File[] = [];
    async function scanFn(entry: FileSystemEntry) {
        if (entry.isDirectory) {
            // 扫描目录
            const reader = (entry as FileSystemDirectoryEntry).createReader();
            const entries = await new Promise<FileSystemEntry[]>((resolve, reject) =>
                reader.readEntries(resolve, reject)
            );
            // 递归扫描
            await Promise.all(entries.map((entry, index) => scanFn(entry)));
        } else {
            // 读取文件
            const file = await new Promise<File>((resolve, reject) =>
                (entry as FileSystemFileEntry).file(resolve, reject)
            );
            result.push(file);
        }
    }
    await scanFn(entry);
    return result;
}

export default function App() {
    return (
        <input
            type="file"
            multiple
            webkitdirectory="true"
            // 点击上传
            onChange={e => {
                console.log(e.target.files);
            }}
            // 拖拽上传
            onDragOver={e => {
                e.preventDefault();
            }}
            onDrop={e => {
                e.preventDefault();
                for (const item of e.dataTransfer.items) {
                    const entry = item.webkitGetAsEntry();
                    if (!entry) continue;
                    scanFileSystemEntry(entry).then(res => console.log(res));
                }
            }}
        />
    );
}