Files
homaroma/apps/backend/src/routes/upload.ts
T
2026-06-03 08:39:12 +07:00

62 lines
1.7 KiB
TypeScript

import { Elysia, t } from "elysia";
import { join } from "path";
import { mkdir } from "fs/promises";
export const uploadRoute = new Elysia({ prefix: "/upload" })
.post("/", async ({ body, set }) => {
const { file } = body as { file: File };
if (!file) {
set.status = 400;
return { error: "No file uploaded" };
}
// Validate file type
if (!file.type.startsWith("image/")) {
set.status = 400;
return { error: "Only image files are allowed" };
}
console.log(`[Upload] Processing: ${file.name} (${(file.size / 1024).toFixed(2)} KB, ${file.type})`);
// Generate unique filename
const ext = file.name.split(".").pop();
const filename = `${crypto.randomUUID()}.${ext}`;
const uploadDir = join(process.cwd(), "public", "uploads");
const filePath = join(uploadDir, filename);
try {
// Ensure directory exists
await mkdir(uploadDir, { recursive: true });
// Write file using Bun.write
await Bun.write(filePath, await file.arrayBuffer());
const APP_URL = process.env.APP_URL || "http://localhost:3000";
const publicUrl = `${APP_URL}/uploads/${filename}`;
console.log(`[Upload] Success: ${filename} -> ${publicUrl}`);
return {
success: true,
url: publicUrl,
filename
};
} catch (err) {
console.error("[Upload] Error:", err);
set.status = 500;
return { error: "Failed to save file" };
}
}, {
body: t.Object({
file: t.File({
maxSize: '5m',
type: ['image/jpeg', 'image/png', 'image/webp', 'image/gif']
})
}),
detail: {
summary: "Upload product image",
tags: ["upload"]
}
});