Files
homaroma/apps/backend/src/routes/upload.js
T
2026-07-28 00:13:57 -04:00

67 lines
2.2 KiB
JavaScript

import { Elysia, t } from "elysia";
import { join } from "path";
import { mkdir } from "fs/promises";
import { randomUUID } from "crypto";
import prisma from "../lib/prisma";
export const uploadRoute = new Elysia({ prefix: "/upload" })
.post("/", async ({ body, set }) => {
const { file } = body;
if (!file) {
set.status = 400;
return { error: "No file uploaded" };
}
// Validate file type
if (!file.type.startsWith("image/") && !file.type.startsWith("video/")) {
set.status = 400;
return { error: "Only image and video 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 = `${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 relativePath = `/uploads/${filename}`;
const mimeType = file.type;
const sizeBytes = file.size;
await prisma.media.create({
data: {
filename,
path: relativePath,
mimeType,
sizeBytes,
}
});
const BACKEND_PUBLIC_URL = process.env.BACKEND_PUBLIC_URL || "http://localhost:3051";
const publicUrl = `${BACKEND_PUBLIC_URL}${relativePath}`;
console.log(`[Upload] Success: ${filename} -> ${publicUrl}`);
return {
success: true,
url: publicUrl,
filename,
path: relativePath
};
}
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"]
}
});
//# sourceMappingURL=upload.js.map