import { NextRequest, NextResponse } from "next/server"; import { authenticateAPIRequest } from "@/app/lib/api-auth"; import sharp from "sharp"; import { db } from "@/db"; import { images } from "@/db/schema"; import { nanoid } from "nanoid"; import { uploadToR2, getContentType } from "@/app/lib/r2-storage"; /** * POST /api/v1/images/upload * Resim yükle ve manipüle et * * Headers: * - Authorization: Bearer * - Content-Type: multipart/form-data * * Body (FormData): * - file: Resim dosyası * - width: Genişlik (px) - opsiyonel, default: 800 * - height: Yükseklik (px) - opsiyonel, default: 600 * - quality: Kalite (1-100) - opsiyonel, default: 90 * - format: Format (jpeg, png, webp, avif) - opsiyonel, default: jpeg */ export async function POST(request: NextRequest) { const auth = await authenticateAPIRequest(request); if (!auth.authenticated) { return NextResponse.json({ error: auth.error }, { status: 401 }); } try { const formData = await request.formData(); const file = formData.get("file") as File; if (!file) { return NextResponse.json( { error: "Dosya bulunamadı" }, { status: 400 } ); } // Dosya boyutu kontrolü (max 10MB) const MAX_FILE_SIZE = 10 * 1024 * 1024; if (file.size > MAX_FILE_SIZE) { return NextResponse.json( { error: "Dosya boyutu çok büyük. Maksimum 10MB olmalıdır." }, { status: 400 } ); } // Dosya tipi kontrolü const allowedMimeTypes = ["image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp", "image/avif"]; if (!allowedMimeTypes.includes(file.type)) { return NextResponse.json( { error: "Geçersiz dosya tipi. Sadece resim dosyaları kabul edilir." }, { status: 400 } ); } // Parametreleri al const widthInput = formData.get("width") as string; const heightInput = formData.get("height") as string; const qualityInput = formData.get("quality") as string; const formatInput = (formData.get("format") as string) || "jpeg"; const width = Math.max(1, Math.min(10000, parseInt(widthInput) || 800)); const height = Math.max(1, Math.min(10000, parseInt(heightInput) || 600)); const quality = Math.max(1, Math.min(100, parseInt(qualityInput) || 90)); const allowedFormats = ["jpeg", "jpg", "png", "webp", "avif"]; const format = allowedFormats.includes(formatInput) ? formatInput : "jpeg"; const bytes = await file.arrayBuffer(); const buffer = Buffer.from(bytes); // Resim manipülasyonu let processedBuffer = sharp(buffer).resize(width, height, { fit: "cover", position: "center", withoutEnlargement: false, }); // Format ve kalite ayarları const normalizedFormat = format === "jpg" ? "jpeg" : format; if (normalizedFormat === "jpeg") { processedBuffer = processedBuffer.jpeg({ quality }); } else if (normalizedFormat === "png") { processedBuffer = processedBuffer.png({ quality }); } else if (normalizedFormat === "webp") { processedBuffer = processedBuffer.webp({ quality }); } else if (normalizedFormat === "avif") { processedBuffer = processedBuffer.avif({ quality }); } const processedImage = await processedBuffer.toBuffer(); const metadata = await sharp(processedImage).metadata(); // Dosya kaydet const fileId = nanoid(); const originalName = file.name; const fileExtension = normalizedFormat === "jpeg" ? "jpg" : normalizedFormat; const fileName = `${fileId}.${fileExtension}`; // R2'ye yükle const contentType = getContentType(fileExtension); const r2Url = await uploadToR2({ buffer: processedImage, fileName, contentType, }); // Veritabanına kaydet const imageId = nanoid(); await db.insert(images).values({ id: imageId, userId: auth.userId!, originalName, fileName, filePath: fileName, // R2'de sadece fileName yeterli url: r2Url, // R2'nin tam URL'si width: metadata.width || null, height: metadata.height || null, quality, format: normalizedFormat, fileSize: processedImage.length, }); const fullImageUrl = r2Url; return NextResponse.json({ success: true, message: "Resim başarıyla yüklendi", data: { image: { id: imageId, url: fullImageUrl, width: metadata.width, height: metadata.height, format: normalizedFormat, fileSize: processedImage.length, }, }, }); } catch (error: any) { console.error("API - Upload hatası:", error); return NextResponse.json( { error: error.message || "Yükleme başarısız" }, { status: 500 } ); } }