pelagia-portal/App/app/api/files/dev/[...key]/route.ts
2026-05-18 23:18:58 +05:30

88 lines
2.5 KiB
TypeScript

import { auth } from "@/auth";
import { NextRequest, NextResponse } from "next/server";
import fs from "fs/promises";
import path from "path";
const UPLOADS_DIR = path.join(process.cwd(), ".dev-uploads");
function resolveFilePath(keySegments: string[]): string {
const relative = path.join(...keySegments);
const resolved = path.resolve(UPLOADS_DIR, relative);
// Prevent path traversal outside the uploads directory
if (!resolved.startsWith(path.resolve(UPLOADS_DIR))) {
throw new Error("Invalid path");
}
return resolved;
}
export async function PUT(
request: NextRequest,
{ params }: { params: Promise<{ key: string[] }> }
) {
if (process.env.NODE_ENV !== "development") {
return NextResponse.json({ error: "Not found" }, { status: 404 });
}
const session = await auth();
if (!session?.user) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const { key } = await params;
let filePath: string;
try {
filePath = resolveFilePath(key);
} catch {
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
}
await fs.mkdir(path.dirname(filePath), { recursive: true });
const buffer = await request.arrayBuffer();
await fs.writeFile(filePath, Buffer.from(buffer));
return new NextResponse(null, { status: 200 });
}
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ key: string[] }> }
) {
if (process.env.NODE_ENV !== "development") {
return NextResponse.json({ error: "Not found" }, { status: 404 });
}
const session = await auth();
if (!session?.user) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const { key } = await params;
let filePath: string;
try {
filePath = resolveFilePath(key);
} catch {
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
}
let fileBuffer: Buffer;
try {
fileBuffer = await fs.readFile(filePath) as Buffer;
} catch {
return NextResponse.json({ error: "File not found" }, { status: 404 });
}
const ext = path.extname(filePath).toLowerCase();
const contentTypeMap: Record<string, string> = {
".pdf": "application/pdf",
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".gif": "image/gif",
".webp": "image/webp",
};
const contentType = contentTypeMap[ext] ?? "application/octet-stream";
return new NextResponse(new Uint8Array(fileBuffer), {
headers: { "Content-Type": contentType },
});
}