import { NextResponse } from "next/server"; import { auth } from "@/app/(auth)/auth"; import { getTripoProviderConfig } from "@/lib/tripo/server"; import { TripoApiError, tripoRequest } from "@/lib/tripo/client"; export const runtime = "nodejs"; export const maxDuration = 60; const ALLOWED_IMAGE_TYPES = new Set(["image/png", "image/jpeg", "image/webp"]); const MAX_UPLOAD_SIZE = 10 * 1024 * 1024; function extractImageToken(data: unknown): string | null { if (!data) return null; if (typeof data === "string") return data.trim() || null; if (typeof data !== "object") return null; const record = data as Record; const tokenCandidates = [record.image_token, record.file_token, record.token]; for (const candidate of tokenCandidates) { if (typeof candidate === "string" && candidate.trim()) { return candidate.trim(); } } return null; } export async function POST(request: Request) { try { const session = await auth(); if (!session?.user?.id) { return NextResponse.json({ success: false, error: "未登录" }, { status: 401 }); } const formData = await request.formData(); const file = formData.get("file"); if (!(file instanceof File)) { return NextResponse.json({ success: false, error: "请上传图片文件" }, { status: 400 }); } if (!ALLOWED_IMAGE_TYPES.has(file.type)) { return NextResponse.json( { success: false, error: "仅支持 PNG/JPEG/WEBP 图片" }, { status: 400 } ); } if (file.size <= 0 || file.size > MAX_UPLOAD_SIZE) { return NextResponse.json( { success: false, error: "图片大小需在 1B~10MB 之间" }, { status: 400 } ); } const config = await getTripoProviderConfig(); const uploadPaths = ["/upload/sts", "/upload"]; let lastError: unknown = null; for (const path of uploadPaths) { try { const submitData = new FormData(); submitData.set("file", file, file.name || "upload.png"); const result = await tripoRequest>(config, { method: "POST", path, formData: submitData, }); const imageToken = extractImageToken(result.data); return NextResponse.json({ success: true, data: { imageToken, file: result.data, }, traceId: result.traceId, }); } catch (error) { lastError = error; if (error instanceof TripoApiError && error.httpStatus === 404) { continue; } throw error; } } throw lastError instanceof Error ? lastError : new Error("图片上传失败"); } catch (error) { if (error instanceof TripoApiError) { return NextResponse.json( { success: false, error: error.message, code: error.code, suggestion: error.suggestion, traceId: error.traceId, }, { status: error.httpStatus || 502 } ); } return NextResponse.json( { success: false, error: error instanceof Error ? error.message : "图片上传失败", }, { status: 500 } ); } }