fix: serve uploads via route handler instead of public/ (standalone 404 fix)
All checks were successful
Deploy / build-and-deploy (push) Successful in 1m49s
All checks were successful
Deploy / build-and-deploy (push) Successful in 1m49s
This commit is contained in:
49
app/uploads/[...path]/route.ts
Normal file
49
app/uploads/[...path]/route.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
const UPLOADS_DIR = path.join(process.cwd(), "data", "uploads");
|
||||
|
||||
export async function GET(
|
||||
_req: NextRequest,
|
||||
{ params }: { params: Promise<{ path: string[] }> }
|
||||
) {
|
||||
const { path: segments } = await params;
|
||||
const filePath = path.join(UPLOADS_DIR, ...segments);
|
||||
|
||||
if (!filePath.startsWith(UPLOADS_DIR)) {
|
||||
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
||||
}
|
||||
|
||||
try {
|
||||
const content = fs.readFileSync(filePath);
|
||||
const ext = path.extname(filePath).toLowerCase();
|
||||
const mime = MIME_MAP[ext] ?? "application/octet-stream";
|
||||
return new NextResponse(content, {
|
||||
headers: {
|
||||
"Content-Type": mime,
|
||||
"Cache-Control": "public, max-age=31536000, immutable",
|
||||
},
|
||||
});
|
||||
} catch {
|
||||
return NextResponse.json({ error: "Not found" }, { status: 404 });
|
||||
}
|
||||
}
|
||||
|
||||
const MIME_MAP: Record<string, string> = {
|
||||
".mp3": "audio/mpeg",
|
||||
".ogg": "audio/ogg",
|
||||
".wav": "audio/wav",
|
||||
".flac": "audio/flac",
|
||||
".m4a": "audio/mp4",
|
||||
".webm": "audio/webm",
|
||||
".mp4": "video/mp4",
|
||||
".avi": "video/x-msvideo",
|
||||
".mov": "video/quicktime",
|
||||
".mkv": "video/x-matroska",
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
".gif": "image/gif",
|
||||
".webp": "image/webp",
|
||||
};
|
||||
Reference in New Issue
Block a user