-
-
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: