77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
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 "";
|
|
}
|
|
}
|
|
|
|
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<string, unknown>;
|
|
const requestOrigin = getRequestOrigin(request);
|
|
const url = resolveDownloadUrl(body.url, requestOrigin);
|
|
if (!url) {
|
|
return NextResponse.json({ success: false, error: "图片地址无效" }, { status: 400 });
|
|
}
|
|
|
|
const name = sanitizeCanvasDownloadFileName(String(body.name || ""), "canvas-image");
|
|
const result = await fetchCanvasDownloadAsset({
|
|
file: { url, name },
|
|
index: 0,
|
|
requestOrigin,
|
|
cookie: request.headers.get("cookie") || "",
|
|
includeSequencePrefix: false,
|
|
});
|
|
|
|
if (!result.ok) {
|
|
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 });
|
|
}
|
|
}
|