Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pu/ignore files #8

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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://github.com/quarklemotion/html5-file-selector",
"repository": "quarklemotion/html5-file-selector",
Expand Down
145 changes: 131 additions & 14 deletions src/Html5FileSelector.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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) {
Expand Down Expand Up @@ -58,6 +93,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) {
Expand All @@ -70,7 +128,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 !== '' ? file.webkitRelativePath : `/${file.name}`),
lastModified: file.lastModified,
lastModifiedDate: file.lastModifiedDate,
name: file.name,
Expand All @@ -80,11 +138,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));
});
}
});
}

Expand All @@ -104,10 +185,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));
Expand Down Expand Up @@ -135,6 +216,36 @@ 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 (entry.isDirectory) {
folderPromises.push(traverseDirectoryHandle(listItem));
}
if (entry.isFile) {
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
Expand All @@ -144,12 +255,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;
Expand Down