-
-
Save amanchopra95/7e5dd52100837d63386c6fd0bb25e1a1 to your computer and use it in GitHub Desktop.
| /** | |
| * 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) => { | |
| object = { | |
| fileObject: file, | |
| fullPath: entry ? entry.fullPath : '', | |
| lastModified: file.lastModified, | |
| lastModifiedDate: file.lastModifiedDate, | |
| name: file.name, | |
| size: file.size, | |
| type: file.type, | |
| webkitRelativePath: file.webkitRelativePath | |
| } | |
| return object; | |
| } | |
| 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 { | |
| dataTransferFiles.push(listItem); | |
| } | |
| } | |
| }); | |
| if (folderPromises.length) { | |
| const flatten = (array) => array.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []); | |
| return Promise.all(folderPromises).then((fileEntries) => { | |
| const flattenedEntries = flatten(fileEntries); | |
| flattenedEntries.forEach((fileEntry) => { | |
| filePromises.push(getFile(fileEntry)); | |
| }); | |
| return handleFilePromises(filePromises, dataTransferFiles); | |
| }); | |
| } else if (filePromises.length) { | |
| return handleFilePromises(filePromises, dataTransferFiles); | |
| } | |
| return Promise.resolve(dataTransferFiles); | |
| } | |
| // Use this function by passing the drop or change event. | |
| const getDroppedOrSelectedFiles = (event) => { | |
| const dataTransfer = event.dataTransfer; | |
| if (dataTransfer && dataTransfer.items) { | |
| return getDataTransferFiles(dataTransfer) | |
| .then((fileList) => { | |
| return Promise.resolve(fileList); | |
| }) | |
| } | |
| const files = []; | |
| const dragDropFileList = dataTransfer && dataTransfer.files; | |
| const inputFieldFileList = event.target && event.target.files; | |
| const fileList = dragDropFileList || inputFieldFileList || []; | |
| for (let i = 0; i < fileList.length; i++) { | |
| files.push(packageFile(fileList[i])); | |
| } | |
| return Promise.resolve(files); | |
| } |
Unfortunately, when you drag and drop a directory in Firefox, the mime-types of files are lost (they show as empty strings).
When you drop the files themselves, the mime-types are fine.
Is there any work-around?
Unfortunately, when you drag and drop a directory in Firefox, the mime-types of files are lost (they show as empty strings). When you drop the files themselves, the mime-types are fine. Is there any work-around?
Simple workaround is to read the file using FileReader and read the first 4 bytes as an arraybuffer and map it to mime type sample code
`const packageFile = (file, entry, hex) => {
object = {
fileObject: file,
fullPath: entry ? entry.fullPath : '',
lastModified: file.lastModified,
lastModifiedDate: file.lastModifiedDate,
name: file.name,
size: file.size,
type: file.type === "" ? getMimetype(hex) : file.type,
webkitRelativePath: file.webkitRelativePath
}
return object;
}
const getFile = (entry) => {
return new Promise((resolve) => {
entry.file((file) => {
let reader = new FileReader();
reader.onload = () => {
console.log(reader);
const uint = new Uint8Array(reader.result);
let bytes = [];
uint.forEach((byte) => {
bytes.push(byte.toString(16));
})
const hex = bytes.join('').toUpperCase();
resolve(packageFile(file, entry, hex));
}
reader.readAsArrayBuffer(file.slice(0, 4));
})
})
}
const getMimetype = (signature) => {
switch (signature) {
case '89504E47':
return 'image/png'
case '47494638':
return 'image/gif'
case '25504446':
return 'application/pdf'
case 'FFD8FFDB':
case 'FFD8FFE0':
return 'image/jpeg'
case '504B0304':
return 'application/zip'
default:
return 'Unknown filetype'
}
}
`
Note: FileReader can be an expensive operation, maybe you can only run only for Firefox
Usage example: