Enhance Vereinsmeisterschaften and Vorstand pages with image support for players and board members. Implement lightbox functionality for player images in Vereinsmeisterschaften. Update CSV handling to include image filenames for better data management. Refactor components to utilize PersonCard for board members, improving code readability and maintainability.
This commit is contained in:
108
server/api/personen/[filename].get.js
Normal file
108
server/api/personen/[filename].get.js
Normal file
@@ -0,0 +1,108 @@
|
||||
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'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user