Skip to content

Instantly share code, notes, and snippets.

@Potat05
Last active November 10, 2023 02:41
Show Gist options
  • Save Potat05/f13e8cce1e4e62b4133f3a5b9a6c9469 to your computer and use it in GitHub Desktop.
Save Potat05/f13e8cce1e4e62b4133f3a5b9a6c9469 to your computer and use it in GitHub Desktop.
Fetch tiny sections of VERY large files without downloading the whole file.
export class SectionFetchableBlob implements Blob {
public readonly url: string;
public readonly size: number;
public readonly type: string;
private readonly start: number;
private readonly end: number;
private constructor(url: string, size: number, type: string, start: number = 0, end: number = size) {
this.url = url;
this.size = size;
this.type = type;
this.start = start;
this.end = end;
}
public static async new(url: string): Promise<SectionFetchableBlob> {
const fet = await fetch(url, { method: 'HEAD' });
const size = parseInt(fet.headers.get('Content-Length')!);
const type = fet.headers.get('Content-Type')!;
return new SectionFetchableBlob(url, size, type);
}
private async getFetch(): Promise<Response> {
return await fetch(this.url, {
headers: {
'Range': `bytes=${this.start}-${this.end}`
}
});
}
private async get(): Promise<Blob> {
return (await this.getFetch()).blob();
}
public async arrayBuffer(): Promise<ArrayBuffer> {
return (await this.get()).arrayBuffer();
}
public slice(start?: number | undefined, end?: number | undefined, contentType?: string | undefined): Blob {
if(start === undefined) {
start = 0;
}
if(end === undefined) {
end = this.size;
}
if(start >= end) {
throw new Error('Invalid slice size.');
}
return new SectionFetchableBlob(this.url, end - start, contentType ?? this.type, this.start + start, this.start + end);
}
public stream(): ReadableStream<Uint8Array> {
throw new Error("Method not implemented.");
}
public async text(): Promise<string> {
return (await this.get()).text();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment