import { NextRequest, NextResponse } from "next/server"; import { writeFile, mkdir } from "fs/promises"; import path from "path"; const IMAGE_TYPES = ["image/jpeg", "image/png", "image/webp", "image/avif"]; const VIDEO_TYPES = ["video/mp4", "video/webm"]; const IMAGE_EXTENSIONS = [".jpg", ".jpeg", ".png", ".webp", ".avif"]; const VIDEO_EXTENSIONS = [".mp4", ".webm"]; const IMAGE_FOLDERS = ["team", "master-classes", "news", "classes"]; const VIDEO_FOLDERS = ["hero"]; const ALL_FOLDERS = [...IMAGE_FOLDERS, ...VIDEO_FOLDERS]; const IMAGE_MAX_SIZE = 5 * 1024 * 1024; // 5MB const VIDEO_MAX_SIZE = 10 * 1024 * 1024; // 10MB export async function POST(request: NextRequest) { let formData: FormData; try { formData = await request.formData(); } catch (e) { const msg = e instanceof Error ? e.message : "Upload failed"; return NextResponse.json( { error: msg.includes("size") || msg.includes("multipart") ? "Файл слишком большой (макс. 10 МБ)" : `Ошибка загрузки: ${msg}` }, { status: 413 } ); } const file = formData.get("file") as File | null; const rawFolder = (formData.get("folder") as string) || "team"; const folder = ALL_FOLDERS.includes(rawFolder) ? rawFolder : "team"; const isVideoFolder = VIDEO_FOLDERS.includes(folder); if (!file) { return NextResponse.json({ error: "No file provided" }, { status: 400 }); } const allowedTypes = isVideoFolder ? VIDEO_TYPES : IMAGE_TYPES; if (!allowedTypes.includes(file.type)) { const msg = isVideoFolder ? "Допустимы только MP4 и WebM" : "Допустимы только JPEG, PNG, WebP и AVIF"; return NextResponse.json({ error: msg }, { status: 400 }); } const maxSize = isVideoFolder ? VIDEO_MAX_SIZE : IMAGE_MAX_SIZE; if (file.size > maxSize) { const label = isVideoFolder ? "10 МБ" : "5 МБ"; return NextResponse.json( { error: `Файл слишком большой (макс. ${label})` }, { status: 400 } ); } // Validate and sanitize filename const ext = path.extname(file.name).toLowerCase() || (isVideoFolder ? ".mp4" : ".webp"); const allowedExts = isVideoFolder ? VIDEO_EXTENSIONS : IMAGE_EXTENSIONS; if (!allowedExts.includes(ext)) { return NextResponse.json( { error: "Недопустимое расширение файла" }, { status: 400 } ); } const baseName = file.name .replace(ext, "") .toLowerCase() .replace(/[^a-z0-9а-яё-]/gi, "-") .replace(/-+/g, "-") .slice(0, 50); const fileName = `${baseName}-${Date.now()}${ext}`; const subDir = isVideoFolder ? path.join("video") : path.join("images", folder); const dir = path.join(process.cwd(), "public", subDir); await mkdir(dir, { recursive: true }); const buffer = Buffer.from(await file.arrayBuffer()); const filePath = path.join(dir, fileName); await writeFile(filePath, buffer); const publicPath = `/${subDir.replace(/\\/g, "/")}/${fileName}`; return NextResponse.json({ path: publicPath }); }