Skip to content

Commit 42d34a6

Browse files
authored
Merge pull request #20 from martinRenou/fix_binary_files_open
Add support for base64 types
2 parents 9581e2e + 18dca6f commit 42d34a6

File tree

1 file changed

+56
-25
lines changed

1 file changed

+56
-25
lines changed

src/drive.ts

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ import { PathExt } from '@jupyterlab/coreutils';
44

55
import { ISignal, Signal } from '@lumino/signaling';
66

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+
718
async function toArray<T>(
819
asyncIterator: AsyncIterableIterator<T>
920
): Promise<T[]> {
@@ -83,36 +94,15 @@ export class FileSystemDrive implements Contents.IDrive {
8394
}
8495

8596
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);
9998
} else {
10099
const content: Contents.IModel[] = [];
101100

102101
for await (const value of localHandle.values()) {
103102
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+
);
116106
} else {
117107
content.push({
118108
name: value.name,
@@ -305,6 +295,47 @@ export class FileSystemDrive implements Contents.IDrive {
305295
return Boolean(matches.length);
306296
}
307297

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+
308339
private _isDisposed = false;
309340
private _fileChanged = new Signal<Contents.IDrive, Contents.IChangedArgs>(
310341
this

0 commit comments

Comments
 (0)