Skip to content

Commit

Permalink
feat: 添加自动识别文件名功能
Browse files Browse the repository at this point in the history
  • Loading branch information
share121 committed Feb 6, 2025
1 parent 0073691 commit 05ee231
Showing 1 changed file with 31 additions and 28 deletions.
59 changes: 31 additions & 28 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,40 @@
import { dirname, join, basename } from "jsr:@std/path";
import { basename, join } from "jsr:@std/path";
import { Mutex } from "npm:async-mutex";
import { downloadChunk } from "./workerpool.ts";

export async function download(
url: string,
filename: string,
dirpath: string,
threads: number,
chunkSize = 5 * 1024 * 1024,
headers: HeadersInit = {}
) {
async function writeFile(buf: ArrayBuffer, pos: number) {
const release = await mutex.acquire();
while (true) {
try {
await file.seek(pos, Deno.SeekMode.Start);
await file.write(new Uint8Array(buf));
break;
} catch (e) {
console.error("%c" + e, "color: red");
}
}
release();
}

async function getContentLength() {
async function getURLInfo() {
const r = await fetch(url, {
method: "HEAD",
headers: headers,
});
return +r.headers.get("content-length")!;
const contentLength = +r.headers.get("content-length")!;
const disposition = r.headers.get("content-disposition");
const filename = (
disposition
?.split(";")
.map((s) => s.trim())
.find((s) => s.startsWith("filename="))
?.split("=")[1] ?? basename(url)
).replace(/[\\/:*?"<>|]/g, "_");
return { filename, contentLength };
}

// 初始化文件
const dirpath = dirname(filename);
await Deno.mkdir(dirpath, { recursive: true });
const file = await Deno.open(filename, { write: true, create: true });

// 读写锁
const mutex = new Mutex();
const { contentLength, filename } = await getURLInfo();
await Deno.mkdir(dirpath, { recursive: true });
const file = await Deno.open(join(dirpath, filename), {
write: true,
create: true,
});

try {
// 获取文件长度
const contentLength = await getContentLength();
const chunkCount = Math.ceil(contentLength / chunkSize);
const chunks: Chunk[] = Array.from({ length: chunkCount }, (_, i) => ({
start: i * chunkSize,
Expand All @@ -53,7 +46,17 @@ export async function download(
headers,
chunks,
async (i) => {
await writeFile(i.data, i.origin.start);
const release = await mutex.acquire();
while (true) {
try {
await file.seek(i.origin.start, Deno.SeekMode.Start);
await file.write(new Uint8Array(i.data));
break;
} catch (e) {
console.error("%c" + e, "color: red");
}
}
release();
console.log(`chunk ${i.origin.start} - ${i.origin.end} done`);
},
Infinity
Expand All @@ -73,5 +76,5 @@ if (import.meta.main) {
const url = Deno.args[0];
const threads = +Deno.args[1] || 32;
const dirpath = Deno.args[2] || ".";
await download(url, join(dirpath, basename(url)), threads);
await download(url, join(Deno.cwd(), dirpath), threads);
}

0 comments on commit 05ee231

Please sign in to comment.