diff --git a/src/traverseFileTree.ts b/src/traverseFileTree.ts
index 06665d3..7b74c0b 100644
--- a/src/traverseFileTree.ts
+++ b/src/traverseFileTree.ts
@@ -10,30 +10,28 @@ interface InternalDataTransferItem extends DataTransferItem {
path: string;
}
-function loopFiles(item: InternalDataTransferItem, callback) {
- const dirReader = item.createReader();
- let fileList = [];
+const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => {
+ const flattenFileList = [];
+ const progressFileList = [];
+ files.forEach(file => progressFileList.push(file.webkitGetAsEntry() as any));
+ function loopFiles(item: InternalDataTransferItem) {
+ const dirReader = item.createReader();
- function sequence() {
- dirReader.readEntries((entries: InternalDataTransferItem[]) => {
- const entryList = Array.prototype.slice.apply(entries);
- fileList = fileList.concat(entryList);
+ function sequence() {
+ dirReader.readEntries((entries: InternalDataTransferItem[]) => {
+ const entryList = Array.prototype.slice.apply(entries);
- // Check if all the file has been viewed
- const isFinished = !entryList.length;
+ progressFileList.push(...entryList);
+ // Check if all the file has been viewed
+ const isFinished = !entryList.length;
+ if (!isFinished) {
+ sequence();
+ }
+ });
+ }
- if (isFinished) {
- callback(fileList);
- } else {
- sequence();
- }
- });
+ sequence();
}
-
- sequence();
-}
-
-const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const _traverseFileTree = (item: InternalDataTransferItem, path?: string) => {
if (!item) {
@@ -59,20 +57,23 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte
},
});
}
- callback([file]);
+ flattenFileList.push(file);
}
});
} else if (item.isDirectory) {
- loopFiles(item, (entries: InternalDataTransferItem[]) => {
- entries.forEach(entryItem => {
- _traverseFileTree(entryItem, `${path}${item.name}/`);
- });
- });
+ loopFiles(item);
}
};
- files.forEach(file => {
- _traverseFileTree(file.webkitGetAsEntry() as any);
- });
+
+ function walkFiles() {
+ let wipIndex = 0;
+ while (wipIndex < progressFileList.length) {
+ _traverseFileTree(progressFileList[wipIndex]);
+ wipIndex++;
+ }
+ callback(flattenFileList);
+ }
+ walkFiles();
};
export default traverseFileTree;
diff --git a/tests/uploader.spec.tsx b/tests/uploader.spec.tsx
index b7e060c..ba3e47d 100644
--- a/tests/uploader.spec.tsx
+++ b/tests/uploader.spec.tsx
@@ -25,7 +25,7 @@ const makeFileSystemEntry = item => {
return {
readEntries(handle) {
if (!first) {
- return [];
+ return handle([]);
}
first = false;
@@ -373,7 +373,54 @@ describe('uploader', () => {
beforeEach(() => {
uploader = render();
});
+ it('beforeUpload should run after all children files are parsed', done => {
+ const props = { action: '/test', directory: true, accept: '.png' };
+ const mockBeforeUpload = jest.fn();
+ const beforeUpload = (file, fileList) => {
+ console.log('beforeUpload', file, fileList);
+ mockBeforeUpload(file, fileList);
+ };
+ const Test = () => {
+ return ;
+ };
+ const { container } = render();
+ const files = {
+ name: 'foo',
+ children: [
+ {
+ name: 'bar',
+ children: [
+ {
+ name: '1.png',
+ },
+ {
+ name: '2.png',
+ },
+ {
+ name: 'rc',
+ children: [
+ {
+ name: '5.webp',
+ },
+ {
+ name: '4.webp',
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ };
+ const input = container.querySelector('input')!;
+ fireEvent.drop(input, { dataTransfer: { items: [makeDataTransferItem(files)] } });
+ setTimeout(() => {
+ expect(mockBeforeUpload.mock.calls.length).toBe(2);
+ expect(mockBeforeUpload.mock.calls[0][1].length).toBe(2);
+ expect(mockBeforeUpload.mock.calls[1][1].length).toBe(2);
+ done();
+ }, 100);
+ });
it('unaccepted type files to upload will not trigger onStart', done => {
const input = uploader.container.querySelector('input')!;
const files = {