import { NextRequest, NextResponse } from "next/server"; import { auth } from "@/app/(auth)/auth"; import { buildAttachmentContentDisposition, fetchCanvasDownloadAsset, sanitizeCanvasDownloadFileName, } from "@/lib/canvas/photoshop-safe-download"; export const runtime = "nodejs"; export const maxDuration = 120; function getRequestOrigin(request: NextRequest): string { const forwardedHost = (request.headers.get("x-forwarded-host") || "").split(",")[0]?.trim(); const forwardedProto = (request.headers.get("x-forwarded-proto") || "").split(",")[0]?.trim(); if (forwardedHost && forwardedProto) { return `${forwardedProto}://${forwardedHost}`; } return new URL(request.url).origin; } function resolveDownloadUrl(rawUrl: unknown, origin: string): string { const value = String(rawUrl || "").trim(); if (!value) return ""; try { const parsed = new URL(value, origin); if (!/^https?:$/i.test(parsed.protocol)) return ""; return parsed.toString(); } catch (_error) { return ""; } } function resolveDownloadUrls(body: Record, origin: string): string[] { const rawCandidates = Array.isArray(body.urls) ? body.urls : [body.url]; const urls: string[] = []; const seen = new Set(); for (const rawUrl of rawCandidates) { const url = resolveDownloadUrl(rawUrl, origin); if (!url || seen.has(url)) continue; seen.add(url); urls.push(url); } return urls.slice(0, 6); } export async function POST(request: NextRequest) { try { const session = await auth(); if (!session?.user?.id) { return NextResponse.json({ success: false, error: "未登录" }, { status: 401 }); } const body = (await request.json().catch(() => ({}))) as Record; const requestOrigin = getRequestOrigin(request); const urls = resolveDownloadUrls(body, requestOrigin); if (urls.length === 0) { return NextResponse.json({ success: false, error: "图片地址无效" }, { status: 400 }); } const name = sanitizeCanvasDownloadFileName(String(body.name || ""), "canvas-image"); const cookie = request.headers.get("cookie") || ""; let result: Awaited> | null = null; const failures: string[] = []; for (const url of urls) { result = await fetchCanvasDownloadAsset({ file: { url, name }, index: 0, requestOrigin, cookie, includeSequencePrefix: false, }); if (result.ok) break; failures.push(`${url}: ${result.error}`); } if (!result?.ok) { if (failures.length > 0) { console.warn("[CanvasDownloadImage] All candidates failed:", failures); } return NextResponse.json( { success: false, error: result?.error || "图片源文件暂时不可访问" }, { status: 502 } ); } return new NextResponse(result.bytes, { status: 200, headers: { "Content-Type": result.contentType, "Content-Length": String(result.bytes.length), "Content-Disposition": buildAttachmentContentDisposition(result.filename), "Cache-Control": "no-store", }, }); } catch (error) { console.error("[CanvasDownloadImage] Failed:", error); return NextResponse.json({ success: false, error: "图片下载失败" }, { status: 500 }); } }