ghostguild-org/server/api/upload/image.post.js

72 lines
No EOL
1.9 KiB
JavaScript

import { v2 as cloudinary } from 'cloudinary'
// Configure Cloudinary
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET
})
export default defineEventHandler(async (event) => {
try {
// Parse the multipart form data
const formData = await readMultipartFormData(event)
if (!formData || formData.length === 0) {
throw createError({
statusCode: 400,
statusMessage: 'No file provided'
})
}
// Find the file in the form data
const fileData = formData.find(item => item.name === 'file')
if (!fileData) {
throw createError({
statusCode: 400,
statusMessage: 'No file found in upload'
})
}
// Validate file type
if (!fileData.type?.startsWith('image/')) {
throw createError({
statusCode: 400,
statusMessage: 'Invalid file type. Only images are allowed.'
})
}
// Convert buffer to base64 for Cloudinary upload
const base64File = `data:${fileData.type};base64,${fileData.data.toString('base64')}`
// Upload to Cloudinary
const result = await cloudinary.uploader.upload(base64File, {
folder: 'ghost-guild/events',
transformation: [
{ quality: 'auto', fetch_format: 'auto' },
{ width: 1200, height: 630, crop: 'fill' } // Standard social media dimensions
],
allowed_formats: ['jpg', 'png', 'webp', 'gif'],
resource_type: 'image'
})
return {
success: true,
secure_url: result.secure_url,
public_id: result.public_id,
width: result.width,
height: result.height,
format: result.format,
bytes: result.bytes
}
} catch (error) {
console.error('Image upload error:', error)
throw createError({
statusCode: error.statusCode || 500,
statusMessage: error.statusMessage || 'Image upload failed'
})
}
})