import "server-only"; import { getDefaultStorageConfig } from "@/lib/db/queries"; import { findImageArchiveDownloadTask } from "./image-archive-db"; import { extractImageProxySourceUrl, inferOriginalImageUrl } from "@/lib/image-url"; export async function resolveCanvasCdnDownload(urls: string[], filename: string) { const sources = Array.from(new Set(urls.flatMap(url => { const source = extractImageProxySourceUrl(url) || url; return [source, inferOriginalImageUrl(source) || source]; }))); const task = await findImageArchiveDownloadTask(sources, true); const asset = (task?.metadata as { downloadAsset?: { status?: string; url?: string; contentType?: string; bytes?: number } } | null)?.downloadAsset; if (asset?.status !== "ready" || !asset.url || asset.contentType !== "image/png") return { task, direct: null }; const config = await getDefaultStorageConfig(); if (config?.type !== "qiniu-kodo" || !config.publicUrl || !config.isEnabled) return { task, direct: null }; const url = new URL(asset.url); const base = new URL(config.publicUrl); const origin = process.env.CANVAS_QINIU_ORIGIN_URL; if (origin && url.origin === new URL(origin).origin) url.host = base.host; if (base.protocol !== "https:" || url.origin !== base.origin || !(url.pathname.startsWith(base.pathname.replace(/\/$/, "") + "/"))) return { task, direct: null }; // attname is interpreted by Kodo/CDN as Content-Disposition, including Chinese // filenames. Keep all processing/auth parameters intact for correct cache keys. url.searchParams.set("attname", filename); return { task, direct: { delivery: "cdn", downloadUrl: url.toString(), filename, bytes: asset.bytes || 0 } }; }