AllAi/apps/web/app/api/nano-banana/uploads/route.ts
2025-11-14 21:54:04 +03:00

64 lines
2.0 KiB
TypeScript

import { NextResponse } from "next/server";
import { promises as fs } from "fs";
import path from "path";
import { randomUUID } from "crypto";
const UPLOAD_DIR = path.join(process.cwd(), "public", "nano-banana", "uploads");
const MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024; // 10MB
const ALLOWED_MIME = new Set(["image/png", "image/jpeg", "image/webp"]);
function getExtension(file: File) {
const fromType =
file.type === "image/png"
? "png"
: file.type === "image/jpeg"
? "jpg"
: file.type === "image/webp"
? "webp"
: null;
if (fromType) return fromType;
const ext = path.extname(file.name).replace(".", "");
if (ext) return ext;
return "png";
}
export async function POST(req: Request) {
try {
const formData = await req.formData();
const file = formData.get("file");
if (!(file instanceof File)) {
return NextResponse.json({ message: "File is required." }, { status: 400 });
}
if (!ALLOWED_MIME.has(file.type)) {
return NextResponse.json({ message: "Unsupported file type." }, { status: 415 });
}
if (file.size > MAX_FILE_SIZE_BYTES) {
return NextResponse.json({ message: "File is too large." }, { status: 413 });
}
await fs.mkdir(UPLOAD_DIR, { recursive: true });
const filename = `${randomUUID()}.${getExtension(file)}`;
const filePath = path.join(UPLOAD_DIR, filename);
const buffer = Buffer.from(await file.arrayBuffer());
await fs.writeFile(filePath, buffer);
const relativePath = `/nano-banana/uploads/${filename}`;
const host = req.headers.get("x-forwarded-host") ?? req.headers.get("host");
const protocol = req.headers.get("x-forwarded-proto") ?? (host?.includes("localhost") ? "http" : "https");
const origin = host ? `${protocol}://${host}` : "";
const url = origin ? new URL(relativePath, origin).toString() : relativePath;
return NextResponse.json({ url }, { status: 201 });
} catch (error) {
console.error(error);
return NextResponse.json({ message: "Failed to upload file." }, { status: 500 });
}
}