Files
FTP/app/api/files/upload/route.ts
asabizanjo 423ce1bc6d gucci
2025-12-11 01:05:24 +00:00

82 lines
2.2 KiB
TypeScript

import { NextResponse } from "next/server";
import { prisma } from "@/lib/db";
import { getSessionUser } from "@/lib/auth";
import { uploadToR2 } from "@/lib/r2";
const MAX_UPLOAD_SIZE = 10 * 1024 * 1024 * 1024; // 10GB in bytes
function serializeFile(file: Awaited<ReturnType<typeof prisma.file.create>>) {
return {
id: file.id,
key: file.key,
name: file.name,
relativePath: file.relativePath,
contentType: file.contentType,
sizeBytes: Number(file.sizeBytes),
createdAt: file.createdAt,
};
}
export async function POST(req: Request) {
const session = await getSessionUser();
if (!session) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const formData = await req.formData();
const files = formData.getAll("files") as File[];
if (!files.length) {
return NextResponse.json(
{ error: "No files received in 'files' field." },
{ status: 400 }
);
}
// Check total upload size
const totalSize = files.reduce((acc, file) => acc + (file instanceof File ? file.size : 0), 0);
if (totalSize > MAX_UPLOAD_SIZE) {
return NextResponse.json(
{ error: "Total upload size exceeds 10GB limit." },
{ status: 413 }
);
}
const uploaded = [];
for (const file of files) {
if (!(file instanceof File)) continue;
const arrayBuffer = await file.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
const fileWithPath = file as File & { webkitRelativePath?: string };
const relativePath =
fileWithPath.webkitRelativePath ?? fileWithPath.name ?? "unnamed";
const normalizedPath = relativePath.replace(/\\/g, "/");
const name = normalizedPath.split("/").pop() ?? normalizedPath;
const key = `${session.userId}/${Date.now()}-${normalizedPath}`;
const contentType = file.type || "application/octet-stream";
await uploadToR2({
key,
contentType,
body: buffer,
});
const record = await prisma.file.create({
data: {
key,
name,
relativePath: normalizedPath,
contentType,
sizeBytes: BigInt(file.size),
userId: session.userId,
},
});
uploaded.push(serializeFile(record));
}
return NextResponse.json({ ok: true, files: uploaded });
}