@@ -4,6 +4,17 @@ import { PathExt } from '@jupyterlab/coreutils';
4
4
5
5
import { ISignal , Signal } from '@lumino/signaling' ;
6
6
7
+ function arrayBufferToBase64 ( buffer : ArrayBuffer ) : string {
8
+ let binary = '' ;
9
+ const bytes = new Uint8Array ( buffer ) ;
10
+
11
+ for ( let i = 0 ; i < bytes . byteLength ; i ++ ) {
12
+ binary += String . fromCharCode ( bytes [ i ] ) ;
13
+ }
14
+
15
+ return window . btoa ( binary ) ;
16
+ }
17
+
7
18
async function toArray < T > (
8
19
asyncIterator : AsyncIterableIterator < T >
9
20
) : Promise < T [ ] > {
@@ -83,36 +94,15 @@ export class FileSystemDrive implements Contents.IDrive {
83
94
}
84
95
85
96
if ( localHandle . kind === 'file' ) {
86
- const file = await localHandle . getFile ( ) ;
87
-
88
- return {
89
- name : file . name ,
90
- path : PathExt . join ( parentPath , localPath ) ,
91
- created : new Date ( file . lastModified ) . toISOString ( ) ,
92
- last_modified : new Date ( file . lastModified ) . toISOString ( ) ,
93
- format : 'text' ,
94
- content : await file . text ( ) ,
95
- writable : true ,
96
- type : 'file' ,
97
- mimetype : 'text/plain'
98
- } ;
97
+ return this . getFileModel ( localHandle , parentPath , true ) ;
99
98
} else {
100
99
const content : Contents . IModel [ ] = [ ] ;
101
100
102
101
for await ( const value of localHandle . values ( ) ) {
103
102
if ( value . kind === 'file' ) {
104
- const file = await value . getFile ( ) ;
105
- content . push ( {
106
- name : file . name ,
107
- path : PathExt . join ( parentPath , localPath , file . name ) ,
108
- created : new Date ( file . lastModified ) . toISOString ( ) ,
109
- last_modified : new Date ( file . lastModified ) . toISOString ( ) ,
110
- format : 'text' ,
111
- content : await file . text ( ) ,
112
- writable : true ,
113
- type : 'file' ,
114
- mimetype : 'text/plain'
115
- } ) ;
103
+ content . push (
104
+ await this . getFileModel ( value , PathExt . join ( parentPath , localPath ) )
105
+ ) ;
116
106
} else {
117
107
content . push ( {
118
108
name : value . name ,
@@ -305,6 +295,47 @@ export class FileSystemDrive implements Contents.IDrive {
305
295
return Boolean ( matches . length ) ;
306
296
}
307
297
298
+ private async getFileModel (
299
+ handle : FileSystemFileHandle ,
300
+ path : string ,
301
+ content ?: boolean
302
+ ) : Promise < Contents . IModel > {
303
+ const file = await handle . getFile ( ) ;
304
+ let format : Contents . FileFormat ;
305
+ let fileContent : any = null ;
306
+
307
+ // We assume here image, audio and video mimetypes are all and only binary files we'll encounter
308
+ if (
309
+ file . type &&
310
+ file . type . split ( '/' ) &&
311
+ [ 'image' , 'audio' , 'video' ] . includes ( file . type . split ( '/' ) [ 0 ] )
312
+ ) {
313
+ format = 'base64' ;
314
+ } else {
315
+ format = 'text' ;
316
+ }
317
+
318
+ if ( content ) {
319
+ if ( format === 'base64' ) {
320
+ fileContent = arrayBufferToBase64 ( await file . arrayBuffer ( ) ) ;
321
+ } else {
322
+ fileContent = await file . text ( ) ;
323
+ }
324
+ }
325
+
326
+ return {
327
+ name : file . name ,
328
+ path : PathExt . join ( path , file . name ) ,
329
+ created : new Date ( file . lastModified ) . toISOString ( ) ,
330
+ last_modified : new Date ( file . lastModified ) . toISOString ( ) ,
331
+ format,
332
+ content : fileContent ,
333
+ writable : true ,
334
+ type : 'file' ,
335
+ mimetype : file . type
336
+ } ;
337
+ }
338
+
308
339
private _isDisposed = false ;
309
340
private _fileChanged = new Signal < Contents . IDrive , Contents . IChangedArgs > (
310
341
this
0 commit comments