51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
"use server"
|
|
|
|
import { writeFile, mkdir } from "fs/promises"
|
|
import { join } from "path"
|
|
import { v4 as uuidv4 } from "uuid"
|
|
|
|
export async function uploadImage(data: FormData) {
|
|
const file: File | null = data.get("file") as unknown as File
|
|
|
|
if (!file) {
|
|
throw new Error("No file uploaded")
|
|
}
|
|
|
|
const bytes = await file.arrayBuffer()
|
|
const buffer = Buffer.from(bytes)
|
|
|
|
// Validate mime type (basic check)
|
|
if (!file.type.startsWith("image/")) {
|
|
throw new Error("Only images are allowed")
|
|
}
|
|
|
|
// Create uploads directory if it doesn't exist
|
|
// We organize by generic uploads folder for now, or per plan?
|
|
// Let's optimize for simplicity: /public/uploads/YYYY/MM
|
|
|
|
const now = new Date()
|
|
const year = now.getFullYear()
|
|
const month = String(now.getMonth() + 1).padStart(2, '0')
|
|
const params = data.get("planId") ? String(data.get("planId")) : "misc"
|
|
|
|
// Use /uploads/planId/ to keep it somewhat organized or cleanup-able
|
|
const relativeDir = join("uploads", params)
|
|
const uploadDir = join(process.cwd(), "public", relativeDir)
|
|
|
|
try {
|
|
await mkdir(uploadDir, { recursive: true })
|
|
} catch (e) {
|
|
// ignore if exists
|
|
}
|
|
|
|
// Generate filename
|
|
const ext = file.name.split('.').pop() || "jpg"
|
|
const filename = `${uuidv4()}.${ext}`
|
|
const filepath = join(uploadDir, filename)
|
|
|
|
await writeFile(filepath, buffer)
|
|
|
|
// Return the public URL
|
|
return `/${relativeDir}/${filename}`
|
|
}
|