Bulk Thumbnails upload
Deploy / deploy (push) Successful in 2m50s

This commit is contained in:
twotalesanimation
2026-08-06 12:59:28 +02:00
parent 7b36329769
commit 6b15bae62a
3 changed files with 378 additions and 1 deletions
@@ -0,0 +1,41 @@
import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/auth";
import { db } from "@/lib/db";
import { uploadToHetzner } from "@/lib/storage";
import { revalidatePath } from "next/cache";
/**
* POST /api/batch-upload/thumbnails/upload
* FormData: { projectId, shotId, file (image) }
*/
export async function POST(req: NextRequest) {
const session = await auth();
if (!session?.user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
if (!["ADMIN", "PRODUCER", "SUPERVISOR"].includes(session.user.role)) {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
const formData = await req.formData();
const file = formData.get("file") as File | null;
const shotId = formData.get("shotId") as string | null;
const projectId = formData.get("projectId") as string | null;
if (!file || !shotId || !projectId) {
return NextResponse.json({ error: "file, shotId and projectId are required" }, { status: 400 });
}
if (!file.type.startsWith("image/")) {
return NextResponse.json({ error: "File must be an image" }, { status: 400 });
}
const shot = await db.shot.findFirst({ where: { id: shotId, projectId }, select: { id: true } });
if (!shot) return NextResponse.json({ error: "Shot not found" }, { status: 404 });
const buffer = Buffer.from(await file.arrayBuffer());
const { key } = await uploadToHetzner(buffer, file.name, file.type, "image");
const thumbnailUrl = `/api/files/${key}`;
await db.shot.update({ where: { id: shotId }, data: { thumbnailUrl } });
revalidatePath(`/projects/${projectId}`);
return NextResponse.json({ success: true, thumbnailUrl });
}