Refactor image URL handling: Update API routes to return image URLs via the API instead of direct paths, ensuring consistency across avatar and background uploads. Introduce normalization functions for avatar and background URLs to maintain compatibility with existing URLs.
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 2m57s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 2m57s
This commit is contained in:
86
app/api/backgrounds/[filename]/route.ts
Normal file
86
app/api/backgrounds/[filename]/route.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { readFile } from "fs/promises";
|
||||
import { join } from "path";
|
||||
import { existsSync } from "fs";
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ filename: string }> }
|
||||
) {
|
||||
try {
|
||||
const { filename } = await params;
|
||||
|
||||
// Sécuriser le nom de fichier pour éviter les path traversal
|
||||
if (
|
||||
!filename ||
|
||||
filename.includes("..") ||
|
||||
filename.includes("/") ||
|
||||
filename.includes("\\")
|
||||
) {
|
||||
return NextResponse.json(
|
||||
{ error: "Nom de fichier invalide" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Décoder le nom de fichier (au cas où il contient des caractères encodés)
|
||||
const decodedFilename = decodeURIComponent(filename);
|
||||
|
||||
// Chemin vers le fichier background
|
||||
const backgroundsDir = join(
|
||||
process.cwd(),
|
||||
"public",
|
||||
"uploads",
|
||||
"backgrounds"
|
||||
);
|
||||
const filepath = join(backgroundsDir, decodedFilename);
|
||||
|
||||
// Vérifier que le fichier existe
|
||||
if (!existsSync(filepath)) {
|
||||
return NextResponse.json(
|
||||
{ error: "Image de fond non trouvée" },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
// Lire le fichier
|
||||
const fileBuffer = await readFile(filepath);
|
||||
|
||||
// Déterminer le type MIME basé sur l'extension
|
||||
const extension = decodedFilename.split(".").pop()?.toLowerCase();
|
||||
let contentType = "image/jpeg"; // par défaut
|
||||
|
||||
switch (extension) {
|
||||
case "png":
|
||||
contentType = "image/png";
|
||||
break;
|
||||
case "gif":
|
||||
contentType = "image/gif";
|
||||
break;
|
||||
case "webp":
|
||||
contentType = "image/webp";
|
||||
break;
|
||||
case "svg":
|
||||
contentType = "image/svg+xml";
|
||||
break;
|
||||
case "jpg":
|
||||
case "jpeg":
|
||||
default:
|
||||
contentType = "image/jpeg";
|
||||
}
|
||||
|
||||
// Retourner l'image avec les bons headers
|
||||
return new NextResponse(fileBuffer, {
|
||||
headers: {
|
||||
"Content-Type": contentType,
|
||||
"Cache-Control": "public, max-age=31536000, immutable",
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error serving background:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la récupération de l'image de fond" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user