This repository has been archived on 2023-11-29. You can view files and clone it, but cannot push or open issues or pull requests.
Uloz.to-rychle/downloader.ts

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;
}
}