diff --git a/main.ts b/main.ts index 39b335a..901517f 100644 --- a/main.ts +++ b/main.ts @@ -2,19 +2,32 @@ import { basename, join } from "jsr:@std/path"; import { Mutex } from "npm:async-mutex"; import { downloadChunk } from "./workerpool.ts"; -export async function download( - url: string, - dirpath: string, - threads: number, +export async function download({ + url, + dirpath, + threads, chunkSize = 5 * 1024 * 1024, - headers: HeadersInit = {} -) { + headers = {}, + startChunk = 0, + endChunk = Infinity, +}: { + url: string; + dirpath: string; + threads: number; + chunkSize?: number; + headers?: HeadersInit; + startChunk?: number; + endChunk?: number; +}) { async function getURLInfo() { const r = await fetch(url, { method: "HEAD", headers: headers, }); - const contentLength = +r.headers.get("content-length")!; + const contentLength = Math.min( + +r.headers.get("content-length")!, + endChunk - startChunk + 1 + ); const disposition = r.headers.get("content-disposition"); const filename = ( disposition @@ -38,8 +51,8 @@ export async function download( try { const chunkCount = Math.ceil(contentLength / chunkSize); const chunks: Chunk[] = Array.from({ length: chunkCount }, (_, i) => ({ - start: i * chunkSize, - end: Math.min((i + 1) * chunkSize, contentLength) - 1, + start: startChunk + i * chunkSize, + end: startChunk + Math.min((i + 1) * chunkSize, contentLength) - 1, })); await downloadChunk( threads, @@ -79,5 +92,13 @@ if (import.meta.main) { const url = Deno.args[0]; const threads = +Deno.args[1] || 32; const dirpath = Deno.args[2] || "."; - await download(url, join(Deno.cwd(), dirpath), threads); + const startChunk = +Deno.args[3] || 0; + const endChunk = +Deno.args[4] || Infinity; + await download({ + url, + dirpath: join(Deno.cwd(), dirpath), + threads, + startChunk, + endChunk, + }); } diff --git a/main_test.ts b/main_test.ts index 85fe2e5..d99cfcc 100644 --- a/main_test.ts +++ b/main_test.ts @@ -10,7 +10,42 @@ Deno.test("Download ISO file test", async () => { const threads = 32; console.time("Download ISO file test"); - const outputPath = await download(url, dirpath, threads); + const outputPath = await download({ url, dirpath, threads }); + console.timeEnd("Download ISO file test"); + + console.time("Calculate file hash test"); + const file = await Deno.open(outputPath, { read: true }); + const readableStream = file.readable; + const fileHashBuffer = await crypto.subtle.digest("SHA-256", readableStream); + const fileHash = encodeHex(fileHashBuffer); + console.log(fileHash); + console.timeEnd("Calculate file hash test"); + assertEquals( + fileHash, + "6f6a087a4a8326fdb55971d95855f1185f5b547dfe92cf770da4ec555b763d3f" + ); +}); + +Deno.test("Download ISO file test", async () => { + const url = + "https://mirrors.tuna.tsinghua.edu.cn/debian-cd/12.9.0-live/amd64/iso-hybrid/debian-live-12.9.0-amd64-kde.iso"; + const dirpath = "."; + const threads = 32; + + console.time("Download ISO file test"); + const outputPath = await download({ + url, + dirpath, + threads, + startChunk: 0, + endChunk: 700, + }); + await download({ + url, + dirpath, + threads, + startChunk: 700, + }); console.timeEnd("Download ISO file test"); console.time("Calculate file hash test");