@@ -34,30 +34,62 @@ export class DropzoneService {
34
34
return item . webkitGetAsEntry ( ) || item . getAsFile ( ) ;
35
35
}
36
36
37
- private _getFilesFromEntry ( entry : FileSystemEntry | File ) : Promise < File [ ] > {
38
- return new Promise < File [ ] > ( ( resolve ) => {
39
- if ( entry instanceof File ) {
40
- return resolve ( [ entry ] ) ;
41
- }
37
+ private async _getFilesFromEntry ( entry : FileSystemEntry | File ) : Promise < File [ ] > {
38
+ if ( entry instanceof File ) {
39
+ return [ entry ] ;
40
+ }
42
41
43
- if ( this . _isFile ( entry ) ) {
44
- return entry . file ( ( f ) => resolve ( [ f ] ) ) ;
45
- }
42
+ if ( this . _isFile ( entry ) ) {
43
+ const file = await this . _readFilePromise ( entry ) ;
44
+ return [ file ] ;
45
+ }
46
+
47
+ if ( this . _isDirectory ( entry ) ) {
48
+ const entries = await this . _readDirectoryWithoutLimit ( entry ) ;
49
+ const children = entries . map ( ( e ) => this . _getFilesFromEntry ( e ) ) ;
46
50
47
- if ( this . _isDirectory ( entry ) ) {
48
- const reader = entry . createReader ( ) ;
51
+ const files = await Promise . all ( children ) ;
52
+ return this . _flattenFiles ( files ) ;
53
+ }
54
+
55
+ return [ ] ;
56
+ }
49
57
50
- reader . readEntries ( async ( entries ) => {
51
- const children = entries . map ( ( e ) => this . _getFilesFromEntry ( e ) ) ;
52
- const files = await Promise . all ( children ) ;
58
+ /**
59
+ * In Chrome >= 77, the `readEntries` method returns only 100 files.
60
+ * To achieve a consistent behavior across browsers and not restrict user interaction,
61
+ * we break the limit by recursively calling `readEntries`.
62
+ */
63
+ private async _readDirectoryWithoutLimit ( entry : FileSystemDirectoryEntry ) : Promise < FileSystemEntry [ ] > {
64
+ const reader = entry . createReader ( ) ;
65
+ let entries : FileSystemEntry [ ] = [ ] ;
53
66
54
- return resolve ( this . _flattenFiles ( files ) ) ;
55
- } ) ;
67
+ const readEntries = async ( ) => {
68
+ const children = await this . _readDirectoryPromise ( reader ) ;
69
+
70
+ if ( children . length ) {
71
+ entries = entries . concat ( children ) ;
72
+ await readEntries ( ) ;
56
73
}
57
- } ) ;
74
+ } ;
75
+
76
+ await readEntries ( ) ;
77
+ return entries ;
58
78
}
59
79
60
80
private _isFile = ( item : FileSystemEntry ) : item is FileSystemFileEntry => item . isFile ;
61
81
private _isDirectory = ( item : FileSystemEntry ) : item is FileSystemDirectoryEntry => item . isDirectory ;
62
82
private _flattenFiles = ( files : File [ ] [ ] ) => ( [ ] as File [ ] ) . concat ( ...files ) ;
83
+
84
+ private _readFilePromise ( entry : FileSystemFileEntry ) {
85
+ return new Promise < File > ( ( resolve ) => {
86
+ entry . file ( ( file ) => resolve ( file ) ) ;
87
+ } ) ;
88
+ }
89
+
90
+ private _readDirectoryPromise ( reader : FileSystemDirectoryReader ) {
91
+ return new Promise < FileSystemEntry [ ] > ( ( resolve ) => {
92
+ reader . readEntries ( ( entries ) => resolve ( entries ) ) ;
93
+ } ) ;
94
+ }
63
95
}
0 commit comments