prod setup
This commit is contained in:
@@ -4,8 +4,15 @@ import type { APIRoute } from 'astro';
|
||||
import { writeFile, mkdir } from 'node:fs/promises';
|
||||
import { join, extname, basename } from 'node:path';
|
||||
|
||||
const UPLOAD_DIR = join(process.cwd(), 'public', 'img');
|
||||
const ALLOWED_EXT = new Set(['.png', '.jpg', '.jpeg', '.webp', '.svg', '.gif']);
|
||||
const UPLOAD_ROOT = join(process.cwd(), 'data', 'uploads');
|
||||
|
||||
const IMAGE_EXT = new Set(['.png', '.jpg', '.jpeg', '.webp', '.svg', '.gif']);
|
||||
const DOCUMENT_EXT = new Set(['.pdf']);
|
||||
|
||||
const MAX_SIZE: Record<'image' | 'document', number> = {
|
||||
image: 5 * 1024 * 1024,
|
||||
document: 8 * 1024 * 1024,
|
||||
};
|
||||
|
||||
function sanitize(filename: string): string {
|
||||
const name = basename(filename).replace(/[^a-zA-Z0-9._-]/g, '_');
|
||||
@@ -16,25 +23,33 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
const form = await request.formData();
|
||||
const file = form.get('file');
|
||||
const folder = (form.get('folder') as string | null) ?? '';
|
||||
const kindRaw = (form.get('kind') as string | null) ?? 'image';
|
||||
const kind: 'image' | 'document' = kindRaw === 'document' ? 'document' : 'image';
|
||||
|
||||
if (!(file instanceof File)) {
|
||||
return new Response(JSON.stringify({ error: 'no_file' }), { status: 400 });
|
||||
}
|
||||
|
||||
const ext = extname(file.name).toLowerCase();
|
||||
if (!ALLOWED_EXT.has(ext)) {
|
||||
const allowed = kind === 'document' ? DOCUMENT_EXT : IMAGE_EXT;
|
||||
if (!allowed.has(ext)) {
|
||||
return new Response(JSON.stringify({ error: 'invalid_extension' }), { status: 400 });
|
||||
}
|
||||
|
||||
if (file.size > MAX_SIZE[kind]) {
|
||||
return new Response(JSON.stringify({ error: 'file_too_large' }), { status: 400 });
|
||||
}
|
||||
|
||||
const safeFolder = folder.replace(/[^a-zA-Z0-9_-]/g, '');
|
||||
const targetDir = safeFolder ? join(UPLOAD_DIR, safeFolder) : UPLOAD_DIR;
|
||||
const bucket = kind === 'document' ? 'assets' : 'img';
|
||||
const targetDir = safeFolder ? join(UPLOAD_ROOT, bucket, safeFolder) : join(UPLOAD_ROOT, bucket);
|
||||
await mkdir(targetDir, { recursive: true });
|
||||
|
||||
const filename = sanitize(file.name);
|
||||
const buffer = Buffer.from(await file.arrayBuffer());
|
||||
await writeFile(join(targetDir, filename), buffer);
|
||||
|
||||
const url = `/img/${safeFolder ? safeFolder + '/' : ''}${filename}`;
|
||||
const url = `/api/files/${bucket}/${safeFolder ? safeFolder + '/' : ''}${filename}`;
|
||||
return new Response(JSON.stringify({ ok: true, url }), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user