-
-
Notifications
You must be signed in to change notification settings - Fork 576
/
Copy pathfiles.ts
61 lines (48 loc) · 1.93 KB
/
files.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
export function downloadFileURL(filename: string, url: string) {
const element = document.createElement("a");
element.href = url;
element.setAttribute("download", filename);
element.click();
}
export function downloadFileBlob(filename: string, blob: Blob) {
const url = URL.createObjectURL(blob);
downloadFileURL(filename, url);
URL.revokeObjectURL(url);
}
export function downloadFileText(filename: string, text: string) {
const type = filename.endsWith(".svg") ? "image/svg+xml;charset=utf-8" : "text/plain;charset=utf-8";
const blob = new Blob([text], { type });
downloadFileBlob(filename, blob);
}
export async function upload<T extends "text" | "data" | "both">(acceptedExtensions: string, textOrData: T): Promise<UploadResult<T>> {
return new Promise<UploadResult<T>>((resolve, _) => {
const element = document.createElement("input");
element.type = "file";
element.accept = acceptedExtensions;
element.addEventListener(
"change",
async () => {
if (element.files?.length) {
const file = element.files[0];
const filename = file.name;
const type = file.type;
const content = (
textOrData === "text"
? await file.text()
: textOrData === "data"
? new Uint8Array(await file.arrayBuffer())
: textOrData === "both"
? { text: await file.text(), data: new Uint8Array(await file.arrayBuffer()) }
: undefined
) as UploadResultType<T>;
resolve({ filename, type, content });
}
},
{ capture: false, once: true },
);
element.click();
// Once `element` goes out of scope, it has no references so it gets garbage collected along with its event listener, so `removeEventListener` is not needed
});
}
export type UploadResult<T> = { filename: string; type: string; content: UploadResultType<T> };
type UploadResultType<T> = T extends "text" ? string : T extends "data" ? Uint8Array : T extends "both" ? { text: string; data: Uint8Array } : never;