coyotte508 commited on
Commit
075be5d
1 Parent(s): e5bdcf2
.vscode/settings.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "editor.formatOnSave": true
3
+ }
src/lib/WebBlob.ts ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * WebBlob is a Blob implementation for web resources that supports range requests.
3
+ */
4
+
5
+ interface WebBlobCreateOptions {
6
+ /**
7
+ * @default 1_000_000
8
+ *
9
+ * Objects below that size will immediately be fetched and put in RAM, rather
10
+ * than streamed ad-hoc
11
+ */
12
+ cacheBelow?: number;
13
+ /**
14
+ * Custom fetch function to use instead of the default one, for example to use a proxy or edit headers.
15
+ */
16
+ fetch?: typeof fetch;
17
+ }
18
+
19
+ export class WebBlob extends Blob {
20
+ static async create(url: URL, opts?: WebBlobCreateOptions): Promise<Blob> {
21
+ const customFetch = opts?.fetch ?? fetch;
22
+ const response = await customFetch(url, { method: "HEAD" });
23
+
24
+ const size = Number(response.headers.get("content-length"));
25
+ const contentType = response.headers.get("content-type") || "";
26
+ const supportRange = response.headers.get("accept-ranges") === "bytes";
27
+
28
+ if (!supportRange || size < (opts?.cacheBelow ?? 1_000_000)) {
29
+ return await (await customFetch(url)).blob();
30
+ }
31
+
32
+ return new WebBlob(url, 0, size, contentType, true, customFetch);
33
+ }
34
+
35
+ private url: URL;
36
+ private start: number;
37
+ private end: number;
38
+ private contentType: string;
39
+ private full: boolean;
40
+ private fetch: typeof fetch;
41
+
42
+ constructor(url: URL, start: number, end: number, contentType: string, full: boolean, customFetch: typeof fetch) {
43
+ super([]);
44
+
45
+ this.url = url;
46
+ this.start = start;
47
+ this.end = end;
48
+ this.contentType = contentType;
49
+ this.full = full;
50
+ this.fetch = customFetch;
51
+ }
52
+
53
+ override get size(): number {
54
+ return this.end - this.start;
55
+ }
56
+
57
+ override get type(): string {
58
+ return this.contentType;
59
+ }
60
+
61
+ override slice(start = 0, end = this.size): WebBlob {
62
+ if (start < 0 || end < 0) {
63
+ new TypeError("Unsupported negative start/end on FileBlob.slice");
64
+ }
65
+
66
+ const slice = new WebBlob(
67
+ this.url,
68
+ this.start + start,
69
+ Math.min(this.start + end, this.end),
70
+ this.contentType,
71
+ start === 0 && end === this.size ? this.full : false,
72
+ this.fetch
73
+ );
74
+
75
+ return slice;
76
+ }
77
+
78
+ override async arrayBuffer(): Promise<ArrayBuffer> {
79
+ const result = await this.fetchRange();
80
+
81
+ return result.arrayBuffer();
82
+ }
83
+
84
+ override async text(): Promise<string> {
85
+ const result = await this.fetchRange();
86
+
87
+ return result.text();
88
+ }
89
+
90
+ override stream(): ReturnType<Blob["stream"]> {
91
+ const stream = new TransformStream();
92
+
93
+ this.fetchRange()
94
+ .then((response) => response.body?.pipeThrough(stream))
95
+ .catch((error) => stream.writable.abort(error.message));
96
+
97
+ return stream.readable;
98
+ }
99
+
100
+ private fetchRange(): Promise<Response> {
101
+ const fetch = this.fetch; // to avoid this.fetch() which is bound to the instance instead of globalThis
102
+ if (this.full) {
103
+ return fetch(this.url);
104
+ }
105
+ return fetch(this.url, {
106
+ headers: {
107
+ Range: `bytes=${this.start}-${this.end - 1}`,
108
+ },
109
+ });
110
+ }
111
+ }
src/lib/check-dduf.ts ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ export async function checkDduf(url: string): Promise<string> {
2
+
3
+ }
src/routes/+page.svelte CHANGED
@@ -1,2 +1,36 @@
1
- <h1>Welcome to SvelteKit</h1>
2
- <p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { goto } from '$app/navigation';
3
+ import { checkDduf } from '$lib/check-dduf';
4
+
5
+ let url = '';
6
+ let output = '';
7
+
8
+ async function handleSubmit(event: Event) {
9
+ event.preventDefault();
10
+
11
+ output = await checkDduf(url);
12
+ }
13
+ </script>
14
+
15
+ <div class="flex flex-col gap-4 p-4">
16
+ <h1 class="text-xl font-bold">DDUF Check</h1>
17
+
18
+ <form class="flex flex-col gap-4" onsubmit={handleSubmit}>
19
+ <label class="flex flex-col gap-2">
20
+ DDUF URL (resolved url)
21
+ <input
22
+ type="url"
23
+ name="url"
24
+ placeholder="https://huggingface.co/name/repo/main/resolve/file.dduf"
25
+ bind:value={url}
26
+ class="w-full rounded-md border border-gray-300 p-2"
27
+ />
28
+ </label>
29
+
30
+ <button type="submit" class="self-start rounded-md bg-blue-500 p-2 text-white">Check</button>
31
+
32
+ <textarea class="w-full rounded-md border border-gray-300 p-2" rows="10" readonly
33
+ >{output}</textarea
34
+ >
35
+ </form>
36
+ </div>