64 lines
2.0 KiB
TypeScript
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 });
|
|
}
|
|
}
|