94 lines
2 KiB
TypeScript
94 lines
2 KiB
TypeScript
import axios from "axios";
|
|
import { UrlPool } from "./urlpool";
|
|
|
|
export class Downloader {
|
|
|
|
pool: UrlPool;
|
|
chunks: Buffer[] = [];
|
|
downloaded_chunks = 0;
|
|
total_chunks = 0;
|
|
|
|
chunk_size = 512*1024;
|
|
total_size = 0;
|
|
|
|
ready: boolean = false;
|
|
|
|
constructor(pool: UrlPool) {
|
|
this.pool = pool;
|
|
}
|
|
|
|
async init() {
|
|
let url = await this.pool.get();
|
|
if(!url) throw "No available URL in pool!";
|
|
let r = await axios.get(url[1], {
|
|
responseType: 'arraybuffer',
|
|
headers: {
|
|
Range: `bytes=0-0`
|
|
}
|
|
});
|
|
this.total_size = parseInt(r.headers["content-range"].split("/")[1]);
|
|
this.pool.return(url[0]);
|
|
}
|
|
|
|
async download_range(from: number, to: number): Promise<Buffer> {
|
|
return new Promise(async (complete) => {
|
|
|
|
if(to > this.total_size) to = this.total_size;
|
|
|
|
let chunk_count = Math.max(Math.ceil((to-from)/this.chunk_size), 1);
|
|
let chunks: Buffer[] = [];
|
|
let completed = 0;
|
|
|
|
for(let i=0; i<chunk_count; i++) {
|
|
|
|
this.download_chunk(from, to, i).then((result) => {
|
|
chunks[i] = result;
|
|
completed++;
|
|
if(completed == chunk_count) {
|
|
complete(Buffer.concat(chunks));
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
async download_chunk(from: number, to: number, part: number): Promise<Buffer> {
|
|
|
|
let url = await this.pool.get();
|
|
if(!url) throw "No available URL!";
|
|
|
|
let lfrom = from + (part * this.chunk_size) + (part > 0 ? 1 : 0);
|
|
let lto = Math.min(from + (part * this.chunk_size) + this.chunk_size, to);
|
|
if(lfrom == lto) lfrom--;
|
|
|
|
let r = await axios.get(url[1], {
|
|
responseType: 'arraybuffer',
|
|
headers: {
|
|
Range: `bytes=${lfrom}-${lto}`
|
|
}
|
|
});
|
|
|
|
this.pool.return(url[0]);
|
|
return r.data;
|
|
|
|
}
|
|
|
|
async download_part(i: number) {
|
|
|
|
let chunk_size = 10_000_000;
|
|
let from = i*chunk_size;
|
|
let to = (from+chunk_size-1);
|
|
if(to > this.total_size) to = this.total_size;
|
|
|
|
if(this.chunks[i] || from > this.total_size) return false;
|
|
this.total_chunks++;
|
|
|
|
this.chunks[i] = await this.download_range(from, to);
|
|
this.downloaded_chunks++;
|
|
return true;
|
|
|
|
}
|
|
|
|
} |