files.ts 2.49 KB
Newer Older
贾浩@五瓣科技's avatar
贾浩@五瓣科技 committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
// Function to get all files in drop directory
export async function getAllFileEntries(dataTransferItemList: DataTransferItemList): Promise<Array<FileSystemFileEntry>> {
  const fileEntries: Array<FileSystemFileEntry> = [];

  // Use BFS to traverse entire directory/file structure
  const queue: Array<FileSystemFileEntry | FileSystemDirectoryEntry> = [];

  // Unfortunately dataTransferItemList is not iterable i.e. no forEach
  for (let i = 0; i < dataTransferItemList.length; i++) {
    // Note webkitGetAsEntry a non-standard feature and may change
    // Usage is necessary for handling directories
    // + typescript types are kinda wrong - https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/webkitGetAsEntry
    const item = dataTransferItemList[i].webkitGetAsEntry() as FileSystemFileEntry | FileSystemDirectoryEntry | null;
    item && queue.push(item);
  }

  while (queue.length > 0) {
    const entry = queue.shift();
    if (entry?.isFile) {
      fileEntries.push(entry as FileSystemFileEntry);
    } else if (entry?.isDirectory && 'createReader' in entry) {
      queue.push(...await readAllDirectoryEntries(entry.createReader()));
    }
  }
  return fileEntries;
}

// Get all the entries (files or sub-directories) in a directory
// by calling readEntries until it returns empty array
async function readAllDirectoryEntries(directoryReader: DirectoryReader) {
  const entries: Array<FileSystemFileEntry> = [];
  let readEntries = await readEntriesPromise(directoryReader);

  while (readEntries && readEntries.length > 0) {
    entries.push(...readEntries);
    readEntries = await readEntriesPromise(directoryReader);
  }
  return entries;
}

// Wrap readEntries in a promise to make working with readEntries easier
// readEntries will return only some of the entries in a directory
// e.g. Chrome returns at most 100 entries at a time
async function readEntriesPromise(directoryReader: DirectoryReader): Promise<Array<FileSystemFileEntry> | undefined> {
  try {
    return await new Promise((resolve, reject) => {
      directoryReader.readEntries(
        (fileEntry) => {
          resolve(fileEntry as Array<FileSystemFileEntry>);
        },
        reject,
      );
    });
  } catch (err) {}
}

export function convertFileEntryToFile(entry: FileSystemFileEntry): Promise<File> {
  return new Promise((resolve) => {
    entry.file(async(file: File) => {
    //   const newFile = new File([ file ], entry.fullPath, { lastModified: file.lastModified, type: file.type });
      resolve(file);
    });
  });
}