34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
import { NextResponse, type NextRequest } from "next/server";
|
|
import { prisma } from "@/lib/prisma";
|
|
import { errorResponse, ApiError } from "@/lib/api";
|
|
import { getSessionUser } from "@/lib/session";
|
|
import { mimeForKind, readFileBytes, type FileKind } from "@/lib/files";
|
|
|
|
// Any signed-in user can download; mime/extension derived from the asset.
|
|
export async function GET(_req: NextRequest, ctx: { params: Promise<{ id: string }> }) {
|
|
try {
|
|
const user = await getSessionUser();
|
|
if (!user) throw new ApiError(401, "unauthenticated", "Sign in required");
|
|
|
|
const { id } = await ctx.params;
|
|
const file = await prisma.fileAsset.findUnique({ where: { id } });
|
|
if (!file) throw new ApiError(404, "not_found", "File not found");
|
|
|
|
const bytes = await readFileBytes(file.path);
|
|
const mime = mimeForKind(file.kind as FileKind, file.mimeType);
|
|
|
|
const body = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
return new NextResponse(body as ArrayBuffer, {
|
|
status: 200,
|
|
headers: {
|
|
"content-type": mime,
|
|
"content-length": String(bytes.byteLength),
|
|
"content-disposition": `inline; filename="${encodeURIComponent(file.originalName)}"`,
|
|
"cache-control": "private, max-age=3600",
|
|
},
|
|
});
|
|
} catch (err) {
|
|
return errorResponse(err);
|
|
}
|
|
}
|