feat: implement server-side image compression with sharp and cleanup RLS policies

This commit is contained in:
2025-12-18 22:08:28 +01:00
parent d26ebc0b2e
commit 9eb9b41061
5 changed files with 153 additions and 26 deletions

View File

@@ -0,0 +1,69 @@
import sharp from 'sharp';
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextResponse } from 'next/server';
import { v4 as uuidv4 } from 'uuid';
export async function POST(req: Request) {
try {
const supabase = createRouteHandlerClient({ cookies });
// Check session
const { data: { session } } = await supabase.auth.getSession();
if (!session) {
return NextResponse.json({ error: 'Nicht autorisiert' }, { status: 401 });
}
const userId = session.user.id;
const formData = await req.formData();
const file = formData.get('file') as File;
if (!file) {
return NextResponse.json({ error: 'Keine Datei empfangen' }, { status: 400 });
}
// 1. Buffer aus dem Upload erstellen
const arrayBuffer = await file.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
// 2. Mit Sharp optimieren
const optimizedBuffer = await sharp(buffer)
.resize(1200, 1200, {
fit: 'inside',
withoutEnlargement: true
})
.webp({ quality: 80 })
.toBuffer();
// 3. Optimiertes Bild an Supabase Storage senden
// Wir nutzen den userId/uuid.webp Pfad wie im Schema gefordert
const fileName = `${userId}/${uuidv4()}.webp`;
const { data, error } = await supabase.storage
.from('bottles')
.upload(fileName, optimizedBuffer, {
contentType: 'image/webp',
upsert: true
});
if (error) {
console.error('Upload Error:', error);
throw error;
}
// 4. Public URL generieren
const { data: { publicUrl } } = supabase.storage
.from('bottles')
.getPublicUrl(fileName);
return NextResponse.json({
path: data.path,
url: publicUrl
});
} catch (error) {
console.error('Optimization error:', error);
return NextResponse.json({
error: error instanceof Error ? error.message : 'Fehler bei der Bildverarbeitung'
}, { status: 500 });
}
}