diff --git a/src/traverseFileTree.ts b/src/traverseFileTree.ts index 06665d3c..4c1f644f 100644 --- a/src/traverseFileTree.ts +++ b/src/traverseFileTree.ts @@ -10,33 +10,36 @@ interface InternalDataTransferItem extends DataTransferItem { path: string; } -function loopFiles(item: InternalDataTransferItem, callback) { - const dirReader = item.createReader(); - let fileList = []; - - function sequence() { - dirReader.readEntries((entries: InternalDataTransferItem[]) => { - const entryList = Array.prototype.slice.apply(entries); - fileList = fileList.concat(entryList); +const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => { + let restFile = files.length; + const flattenFileList = []; + function loopFiles(item: InternalDataTransferItem, InnerCallback) { + const dirReader = item.createReader(); + let fileList = []; - // Check if all the file has been viewed - const isFinished = !entryList.length; + function sequence() { + dirReader.readEntries((entries: InternalDataTransferItem[]) => { + const entryList = Array.prototype.slice.apply(entries); + fileList = fileList.concat(entryList); - if (isFinished) { - callback(fileList); - } else { - sequence(); - } - }); - } + // Check if all the file has been viewed + const isFinished = !entryList.length; - sequence(); -} + if (isFinished) { + restFile = restFile - 1 + fileList.length; + InnerCallback(fileList); + } else { + sequence(); + } + }); + } -const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => { + sequence(); + } // eslint-disable-next-line @typescript-eslint/naming-convention const _traverseFileTree = (item: InternalDataTransferItem, path?: string) => { if (!item) { + restFile = restFile - 1; return; } // eslint-disable-next-line no-param-reassign @@ -59,7 +62,11 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte }, }); } - callback([file]); + flattenFileList.push(file); + restFile = restFile - 1; + if (restFile === 0) { + callback(flattenFileList); + } } }); } else if (item.isDirectory) { diff --git a/tests/uploader.spec.tsx b/tests/uploader.spec.tsx index b7e060cd..df7749cb 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; @@ -374,6 +374,56 @@ describe('uploader', () => { 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: '3.png', + }, + { + name: '4.png', + }, + ], + }, + ], + }, + ], + }; + const input = container.querySelector('input')!; + fireEvent.drop(input, { dataTransfer: { items: [makeDataTransferItem(files)] } }); + setTimeout(() => { + expect(mockBeforeUpload.mock.calls.length).toBe(4); + expect(mockBeforeUpload.mock.calls[0][1].length).toBe(4); + expect(mockBeforeUpload.mock.calls[1][1].length).toBe(4); + expect(mockBeforeUpload.mock.calls[2][1].length).toBe(4); + expect(mockBeforeUpload.mock.calls[3][1].length).toBe(4); + done(); + }, 100); + }); it('unaccepted type files to upload will not trigger onStart', done => { const input = uploader.container.querySelector('input')!; const files = {