import { createReadStream, statSync } from "node:fs"; import { Readable } from "node:stream"; import { finishDownloadJob, getDownloadJob, jsonError, requireDownloadAccess } from "../helpers/downloadJobs"; function contentDisposition(fileName: string) { const ascii = fileName.replace(/[^\x20-\x7e]/g, "_").replace(/["\\]/g, "_"); return `attachment; filename="${ascii}"; filename*=UTF-8''${encodeURIComponent(fileName)}`; } export async function handle(request: Request) { try { const access = await requireDownloadAccess(request); if (access.error) return access.error; const jobId = new URL(request.url).searchParams.get("jobId") || ""; const job = getDownloadJob(jobId, access.userId); if (!job || job.status !== "ready" || !job.filePath || !job.fileName) { return jsonError("This download is not ready or has already been collected.", 404); } const size = statSync(job.filePath).size; const stream = createReadStream(job.filePath); stream.on("close", () => finishDownloadJob(job)); return new Response(Readable.toWeb(stream) as ReadableStream, { headers: { "Content-Type": job.kind === "playlist" ? "application/zip" : "audio/mpeg", "Content-Length": String(size), "Content-Disposition": contentDisposition(job.fileName), "Cache-Control": "no-store", }, }); } catch (error) { return jsonError(error instanceof Error ? error.message : "Unable to send the file.", 500); } }