You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
1.9 KiB

import { NextRequest, NextResponse } from "next/server";
import { promises as fs } from "fs";
import path from "path";
import { getPool } from "@/lib/database";
import { randomUUID } from "crypto";
export const config = {
api: {
bodyParser: false, // We handle parsing
},
};
export async function POST(req: NextRequest) {
// Get user-id (for dev); in real world, extract from session/token
const userId = req.headers.get("user-id");
if (!userId) {
return NextResponse.json({ error: "Not authenticated" }, { status: 401 });
}
// Parse the form data
try {
const formData = await req.formData();
const file = formData.get("file") as File;
if (!file) {
return NextResponse.json({ error: "No file uploaded" }, { status: 400 });
}
// Only allow .blend, .zip, .jpg, .png, .svg for now
const filename = file.name;
if (!filename.match(/\.(blend|zip|jpg|jpeg|png|svg)$/i)) {
return NextResponse.json(
{ error: "File type not allowed" },
{ status: 400 }
);
}
const saveAs = randomUUID() + path.extname(filename);
const uploadsDir = path.resolve(process.cwd(), "uploads");
await fs.mkdir(uploadsDir, { recursive: true });
const filepath = path.join(uploadsDir, saveAs);
const buffer = Buffer.from(await file.arrayBuffer());
await fs.writeFile(filepath, buffer);
// Write metadata to uploaded_files
const pool = getPool();
const result = await pool.query(
`INSERT INTO uploaded_files (user_id, original_name, file_path, upload_status) VALUES ($1, $2, $3, $4) RETURNING *`,
[userId, filename, filepath, "COMPLETE"]
);
const uploadedFile = result.rows[0];
return NextResponse.json({ success: true, file: uploadedFile });
} catch (err: any) {
console.error(err);
return NextResponse.json(
{ error: err.message || "Upload failed" },
{ status: 500 }
);
}
}