export function getFilesFromDroppedItems(dataTransfer: DataTransfer): Promise { return new Promise((resolve) => { if (!includesFolder(dataTransfer)) { return resolve(dataTransfer.files) } const files: File[] = [] const folderReadQueue = [] // tslint:disable-next-line for (let i = 0; i < dataTransfer.items.length; i++) { const item = dataTransfer.items[i] if (item.kind !== 'file') { continue } const fileSystemEntries = getEntries(item) if (fileSystemEntries) { folderReadQueue.push(fileSystemEntries) } else { const file = item.getAsFile() if (file) { files.push(file) } } } Promise.all(folderReadQueue).then((filesInFolders) => { resolve(files.concat(...filesInFolders)) }) }) } function getEntries(entry: any): Promise | undefined { // convert DataTransferItem to FileSystemEntry first if necessary if (entry.getAsEntry) { return getEntries(entry.getAsEntry()) } if (entry.webkitGetAsEntry) { return getEntries(entry.webkitGetAsEntry()) } // return if item is from a browser that does not support webkitGetAsEntry if (entry.getAsFile) { return } // Processing directories with more than 100 files: // https://github.com/lian-yue/vue-upload-component/commit/9c9d8aafbcef005a2cc598454383ec65205d61ee return new Promise((resolve) => { if (entry.isFile) { entry.file((file: File) => resolve([file])) return } if (entry.isDirectory) { const files: File[] = [] const entryReader = entry.createReader() const readEntries = () => { entryReader.readEntries((entries: any[]) => { const iterateEntry = (i: number) => { if (!entries[i] && i === 0) { return resolve(files) } if (!entries[i]) { return readEntries() } ;(getEntries(entries[i]) as Promise).then((entryFiles: File[]) => { files.push(...entryFiles) iterateEntry(i + 1) }) } iterateEntry(0) }) } readEntries() } if (!entry.isFile && !entry.isDirectory) { resolve([]) } }) } function includesFolder(transfer: DataTransfer): boolean { if (!transfer.files.length) { return true // if dropping only folders, no files will exist } // Loop through the dropped items and log their data for (const item of transfer.items) { if (item.webkitGetAsEntry != null) { const entry = item.webkitGetAsEntry() if (entry && entry.isDirectory) { return true } } } const files: FileList = transfer.files // tslint:disable-next-line for (let i = 0; i < files.length; i++) { // A folder has no type and has a size that is a multiple of 4096 if (!files[i].type && files[i].size % 4096 === 0) { return true } } return false }