109 lines
2.9 KiB
JavaScript
109 lines
2.9 KiB
JavaScript
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'
|
|
})
|
|
}
|
|
})
|
|
|