first commit
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { mkdir, writeFile } from 'node:fs/promises';
|
||||
import { extname, join } from 'node:path';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { UPLOADS_DIR } from '@/lib/db/store';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
const ALLOWED = new Set(['.png', '.jpg', '.jpeg', '.webp', '.gif', '.svg', '.avif']);
|
||||
const MAX_BYTES = 8 * 1024 * 1024; // 8 MB
|
||||
|
||||
export async function POST(req: Request) {
|
||||
let form: FormData;
|
||||
try {
|
||||
form = await req.formData();
|
||||
} catch {
|
||||
return NextResponse.json({ error: 'expected multipart form' }, { status: 400 });
|
||||
}
|
||||
|
||||
const file = form.get('file');
|
||||
if (!(file instanceof File)) {
|
||||
return NextResponse.json({ error: 'no file' }, { status: 400 });
|
||||
}
|
||||
if (file.size > MAX_BYTES) {
|
||||
return NextResponse.json({ error: 'file too large (max 8MB)' }, { status: 413 });
|
||||
}
|
||||
|
||||
const ext = extname(file.name).toLowerCase();
|
||||
if (!ALLOWED.has(ext)) {
|
||||
return NextResponse.json({ error: `unsupported type ${ext}` }, { status: 415 });
|
||||
}
|
||||
|
||||
const name = `${Date.now()}-${randomUUID().slice(0, 8)}${ext}`;
|
||||
const buffer = Buffer.from(await file.arrayBuffer());
|
||||
|
||||
try {
|
||||
await mkdir(UPLOADS_DIR, { recursive: true });
|
||||
await writeFile(join(UPLOADS_DIR, name), buffer);
|
||||
} catch {
|
||||
return NextResponse.json({ error: 'write failed' }, { status: 500 });
|
||||
}
|
||||
|
||||
return NextResponse.json({ url: `/api/uploads/${name}`, name });
|
||||
}
|
||||
Reference in New Issue
Block a user