Extract all files from dropped file(s) or folder(s)

This script will recursively parse dropped/browsed file(s) and folder(s).

by Arjan Haverkamp

HTML

<!doctype html>
<html>
<head>
<title>File Extractor</title>
</head>
<body>

<div id="dropZone" style="border:1px dotted gray;padding:1em">Drop file(s) or folder(s) here<br>or<br><input id="fileInput" type="file" webkitdirectory directory multiple></div>

</body>
</html>

JavaScript

/*
 * Adapted from https://gist.github.com/amanchopra95/7e5dd52100837d63386c6fd0bb25e1a1
 */
const FileExtractor = (() => {

	/**
	 * Traversing directory using promises
	 **/

	const traverseDirectory = entry => {
		const reader = entry.createReader();
		return new Promise(resolveDirectory => {
			const iterationAttempts = [];
			const errorHandler = () => {};

			function readEntries() {
				reader.readEntries(batchEntries => {
					if (!batchEntries.length) {
						resolveDirectory(Promise.all(iterationAttempts))
					} else {
						iterationAttempts.push(Promise.all(batchEntries.map(batchEntry => {
							if (batchEntry.isDirectory) {
								return traverseDirectory(batchEntry);
							}
							return Promise.resolve(batchEntry);
						})));

						readEntries();
					}
				}, errorHandler);
			}

			readEntries();
		});
	}

	const packageFile = (file, entry) => {
		return {
			fileObject: file,
			fullPath: entry ? entry.fullPath : '',
			lastModified: file.lastModified,
			lastModifiedDate: file.lastModifiedDate,
			name: file.name,
			size: file.size,
			type: file.type,
			webkitRelativePath: file.webkitRelativePath
		}
	}

	const getFile = entry => {
		return new Promise(resolve => {
			entry.file(file => {
				resolve(packageFile(file, entry));
			})
		})
	}

	const handleFilePromises = (promises, fileList) => {
		return Promise.all(promises).then(files => {
			files.forEach(file => {
				fileList.push(file);
			});
			return fileList;
		})
	}

	const getDataTransferFiles = dataTransfer => {
		const dataTransferFiles = [];
		const folderPromises = [];
		const filePromises = [];

		[].slice.call(dataTransfer.items).forEach(listItem => {
			if (typeof listItem.webkitGetAsEntry === 'function') {
				const entry = listItem.webkitGetAsEntry();

				if (entry) {
					if (entry.isDirectory) {
						folderPromises.push(traverseDirectory(entry));
					} else {
						filePromises.push(getFile(entry));
					}
				} else...