import fs from 'fs/promises' import path from 'path' import sharp from 'sharp' // Handle both dev and production paths const getDataPath = (filename) => { const cwd = process.cwd() if (cwd.endsWith('.output')) { return path.join(cwd, '../server/data', filename) } return path.join(cwd, 'server/data', filename) } const PERSONEN_DIR = getDataPath('personen') export default defineEventHandler(async (event) => { try { const filename = getRouterParam(event, 'filename') if (!filename) { throw createError({ statusCode: 400, statusMessage: 'Dateiname erforderlich' }) } // Sicherheitsprüfung: Nur erlaubte Dateinamen (UUID-Format) if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.(jpg|jpeg|png|gif|webp)$/i.test(filename)) { throw createError({ statusCode: 400, statusMessage: 'Ungültiger Dateiname' }) } const filePath = path.join(PERSONEN_DIR, filename) // Prüfe ob Datei existiert try { await fs.access(filePath) } catch { throw createError({ statusCode: 404, statusMessage: 'Bild nicht gefunden' }) } // MIME-Type bestimmen const ext = path.extname(filename).toLowerCase() const mimeTypes = { '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.gif': 'image/gif', '.webp': 'image/webp' } const contentType = mimeTypes[ext] || 'application/octet-stream' // Optional: Query-Parameter für Größe const query = getQuery(event) const width = query.width ? parseInt(query.width) : null const height = query.height ? parseInt(query.height) : null let imageBuffer = await fs.readFile(filePath) // Bild verarbeiten falls Größe angegeben if (width || height) { const resizeOptions = {} if (width && height) { resizeOptions.width = width resizeOptions.height = height resizeOptions.fit = 'cover' } else if (width) { resizeOptions.width = width resizeOptions.fit = 'inside' resizeOptions.withoutEnlargement = true } else if (height) { resizeOptions.height = height resizeOptions.fit = 'inside' resizeOptions.withoutEnlargement = true } imageBuffer = await sharp(imageBuffer) .rotate() // EXIF-Orientierung korrigieren .resize(resizeOptions) .toBuffer() } else { // Nur EXIF-Orientierung korrigieren imageBuffer = await sharp(imageBuffer).rotate().toBuffer() } setHeader(event, 'Content-Type', contentType) setHeader(event, 'Cache-Control', 'public, max-age=31536000') return imageBuffer } catch (error) { console.error('Fehler beim Laden des Personenfotos:', error) if (error.statusCode) { throw error } throw createError({ statusCode: 500, statusMessage: 'Fehler beim Laden des Bildes' }) } })