From 5d1edc888e808385c3fccbfe3fd72c6d282a6e92 Mon Sep 17 00:00:00 2001 From: Ching En Cheng Date: Tue, 16 Mar 2021 16:40:28 +0100 Subject: [PATCH 1/5] return proper fullPath when triggered via file selector --- src/Html5FileSelector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Html5FileSelector.js b/src/Html5FileSelector.js index db5b5b9..6de7b82 100644 --- a/src/Html5FileSelector.js +++ b/src/Html5FileSelector.js @@ -70,7 +70,7 @@ function packageFile(file, entry) { } return { fileObject: file, // provide access to the raw File object (required for uploading) - fullPath: entry ? copyString(entry.fullPath) : file.name, + fullPath: entry ? copyString(entry.fullPath) : file.webkitRelativePath, lastModified: file.lastModified, lastModifiedDate: file.lastModifiedDate, name: file.name, From d5b9cdff4532142ee5291e02f0b0d6b5796d6106 Mon Sep 17 00:00:00 2001 From: Ching En Cheng Date: Wed, 16 Jun 2021 14:22:35 +0200 Subject: [PATCH 2/5] bump version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6a0cb53..28a29e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "html5-file-selector", - "version": "2.1.0", + "version": "2.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 53420cd..aa045b7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": false, "name": "html5-file-selector", - "version": "2.1.0", + "version": "2.1.1", "description": "A wrapper library for more easily handling html5 drag/drop and file input file and folder selections", "homepage": "https://www.github.com/quarklemotion/html5-file-selector", "repository": "quarklemotion/html5-file-selector", From 1625c2102e49f8f997e16108f6f0d5b6bfd6b2d8 Mon Sep 17 00:00:00 2001 From: Ching En Cheng Date: Fri, 18 Jun 2021 15:38:31 +0200 Subject: [PATCH 3/5] fix null full path from fileSelectDialog --- src/Html5FileSelector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Html5FileSelector.js b/src/Html5FileSelector.js index 6de7b82..8ca83b5 100644 --- a/src/Html5FileSelector.js +++ b/src/Html5FileSelector.js @@ -70,7 +70,7 @@ function packageFile(file, entry) { } return { fileObject: file, // provide access to the raw File object (required for uploading) - fullPath: entry ? copyString(entry.fullPath) : file.webkitRelativePath, + fullPath: entry ? copyString(entry.fullPath) : (file.webkitRelativePath !== '' ? file.webkitRelativePath : `/${file.name}`), lastModified: file.lastModified, lastModifiedDate: file.lastModifiedDate, name: file.name, From 4999c67dec77305efb029cf76710c629be40fe1f Mon Sep 17 00:00:00 2001 From: ccheng-dev Date: Fri, 13 May 2022 13:40:45 +0200 Subject: [PATCH 4/5] support file handle --- src/Html5FileSelector.js | 103 ++++++++++++++++++++++++++++++++++----- 1 file changed, 92 insertions(+), 11 deletions(-) diff --git a/src/Html5FileSelector.js b/src/Html5FileSelector.js index 8ca83b5..6e8fd48 100644 --- a/src/Html5FileSelector.js +++ b/src/Html5FileSelector.js @@ -58,6 +58,29 @@ function traverseDirectory(entry) { }); } +function traverseDirectoryHandle(listItem) { + return new Promise(async (resolveDirectory) => { + const directoryHandle = await listItem.getAsFileSystemHandle(); + const iterationAttempts = []; + + async function* getFileHandlesRecursively(handle) { + if (handle.kind === 'file') { + yield handle; + } else if (handle.kind === 'directory') { + for await (const folderHandle of handle.values()) { + yield* getFileHandlesRecursively(folderHandle); + } + } + }; + + for await (const fileHandle of getFileHandlesRecursively(directoryHandle)) { + iterationAttempts.push(packageFileHandle(fileHandle, directoryHandle)); + } + + resolveDirectory(iterationAttempts); + }); +} + // package the file in an object that includes the fullPath from the file entry // that would otherwise be lost function packageFile(file, entry) { @@ -80,11 +103,34 @@ function packageFile(file, entry) { }; } -function getFile(entry) { - return new Promise((resolve) => { - entry.file((file) => { - resolve(packageFile(file, entry)); - }); +function packageFileHandle(fileHandle, folderHandle) { + return new Promise(async (resolve) => { + const file = await fileHandle.getFile(); + let fileData = packageFile(file); + fileData.fileObject = fileHandle; + + if (folderHandle) { + let pathArray = await folderHandle.resolve(fileHandle); + const path = pathArray.join('/'); + fileData.fullPath = `/${folderHandle.name}/${path}`; + } + resolve(fileData); + }); +} + +function getFile(entry, listItem) { + return new Promise(async (resolve) => { + if (typeof entry.getFile === 'function') { + const fileHandle = entry.getFile(); + resolve(packageFileHandle(fileHandle)); + } else if (listItem) { + const fileHandle = await listItem.getAsFileSystemHandle(); + resolve(packageFileHandle(fileHandle)); + } else { + entry.file((file) => { + resolve(packageFile(file, entry)); + }); + } }); } @@ -104,10 +150,10 @@ export function getDataTransferFiles(dataTransfer) { const folderPromises = []; const filePromises = []; - [].slice.call(dataTransfer.items).forEach((listItem) => { + [].slice.call(dataTransfer.items).forEach(async (listItem) => { if (typeof listItem.webkitGetAsEntry === 'function') { const entry = listItem.webkitGetAsEntry(); - + if (entry) { if (entry.isDirectory) { folderPromises.push(traverseDirectory(entry)); @@ -135,6 +181,35 @@ export function getDataTransferFiles(dataTransfer) { return Promise.resolve(dataTransferFiles); } +export function getDataTransferFilesWithFileHandles(dataTransfer) { + const dataTransferFiles = []; + const folderPromises = []; + const filePromises = []; + + [].slice.call(dataTransfer.items).forEach((listItem) => { + if (typeof listItem.getAsFileSystemHandle === 'function') { + const entry = listItem.webkitGetAsEntry(); + if (listItem.type === '') { + folderPromises.push(traverseDirectoryHandle(listItem)); + } else { + filePromises.push(getFile(entry, listItem)); + } + } + }); + + if (folderPromises.length) { + return Promise.all(folderPromises).then((promises) => { + promises[0].forEach((promise) => { + filePromises.push(promise); + }); + return handleFilePromises(filePromises, dataTransferFiles); + }); + } else if (filePromises.length) { + return handleFilePromises(filePromises, dataTransferFiles); + } + return Promise.resolve(dataTransferFiles); +} + /** * This function should be called from both the onDrop event from your drag/drop * dropzone as well as from the HTML5 file selector input field onChange event @@ -144,12 +219,18 @@ export function getDataTransferFiles(dataTransfer) { * Returns: an array of File objects, that includes all files within folders * and subfolders of the dropped/selected items. */ -export function getDroppedOrSelectedFiles(event) { +export function getDroppedOrSelectedFiles(event, fileHandle = true) { const dataTransfer = event.dataTransfer; if (dataTransfer && dataTransfer.items) { - return getDataTransferFiles(dataTransfer).then((fileList) => { - return Promise.resolve(fileList); - }); + if (fileHandle) { + return getDataTransferFilesWithFileHandles(dataTransfer).then((fileList) => { + return Promise.resolve(fileList); + }); + } else { + return getDataTransferFiles(dataTransfer).then((fileList) => { + return Promise.resolve(fileList); + }); + } } const files = []; const dragDropFileList = dataTransfer && dataTransfer.files; From caa2ddf32f7fb1afb72db5e946b250e0fe4930ca Mon Sep 17 00:00:00 2001 From: ccheng-dev Date: Mon, 20 Jun 2022 10:44:27 +0200 Subject: [PATCH 5/5] add more ignore file types --- src/Html5FileSelector.js | 44 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/Html5FileSelector.js b/src/Html5FileSelector.js index 6e8fd48..f11e190 100644 --- a/src/Html5FileSelector.js +++ b/src/Html5FileSelector.js @@ -1,6 +1,35 @@ const DEFAULT_FILES_TO_IGNORE = [ '.DS_Store', // OSX indexing file - 'Thumbs.db' // Windows indexing file + '.ds_store', + 'Thumbs.db', // Windows indexing file + '.*~', + '~$*', + '.~lock.*', + '~*.tmp', + '*.~*', + 'Icon\r*', + '._*', + '.*.sw?', + '.*.*sw?', + '.TemporaryItems', + '.Trashes', + '.DocumentRevisions-V100', + '.Trash-*', + '.fseventd', + '.apdisk', + '.directory', + '*.part', + '*.filepart', + '*.crdownload', + '*.kate-swp', + '*.gnucash.tmp-*', + '.synkron.*', + '.sync.ffs_db', + '.symform', + '.symform-store', + '.fuse_hidden*', + '*.unison', + '.nfs*', ]; // map of common (mostly media types) mime types to use when the browser does not supply the mime type @@ -19,7 +48,13 @@ const EXTENSION_TO_MIME_TYPE_MAP = { }; function shouldIgnoreFile(file) { - return DEFAULT_FILES_TO_IGNORE.indexOf(file.name) >= 0; + let isInignoredList = false; + _.each(DEFAULT_FILES_TO_IGNORE, (ignoreFile) => { + if (file.name.match(new RegExp(ignoreFile))) { + isInignoredList = true; + } + }); + return isInignoredList; } function copyString(aString) { @@ -189,9 +224,10 @@ export function getDataTransferFilesWithFileHandles(dataTransfer) { [].slice.call(dataTransfer.items).forEach((listItem) => { if (typeof listItem.getAsFileSystemHandle === 'function') { const entry = listItem.webkitGetAsEntry(); - if (listItem.type === '') { + if (entry.isDirectory) { folderPromises.push(traverseDirectoryHandle(listItem)); - } else { + } + if (entry.isFile) { filePromises.push(getFile(entry, listItem)); } }