61 lines
1.8 KiB
JavaScript
61 lines
1.8 KiB
JavaScript
|
|
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
|
||
|
|
import { join } from 'node:path'
|
||
|
|
import { readMultipartFormData } from 'h3'
|
||
|
|
|
||
|
|
const publicDir = './public'
|
||
|
|
|
||
|
|
const allowedFolders = ['scores', 'pubs', 'album_art', 'images', 'hdp_images']
|
||
|
|
const allowedExtensions = ['.pdf', '.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.mp3', '.wav', '.ogg']
|
||
|
|
|
||
|
|
function getFolderPath(folder) {
|
||
|
|
return join(publicDir, folder)
|
||
|
|
}
|
||
|
|
|
||
|
|
function sanitizeFilename(filename) {
|
||
|
|
return filename.replace(/[^a-zA-Z0-9._-]/g, '_')
|
||
|
|
}
|
||
|
|
|
||
|
|
export default defineEventHandler(async (event) => {
|
||
|
|
const query = getQuery(event)
|
||
|
|
const folder = query.folder
|
||
|
|
|
||
|
|
if (!folder || !allowedFolders.includes(folder)) {
|
||
|
|
throw createError({ statusCode: 400, message: 'Invalid folder' })
|
||
|
|
}
|
||
|
|
|
||
|
|
const folderPath = getFolderPath(folder)
|
||
|
|
|
||
|
|
if (!existsSync(folderPath)) {
|
||
|
|
mkdirSync(folderPath, { recursive: true })
|
||
|
|
}
|
||
|
|
|
||
|
|
const formData = await readMultipartFormData(event)
|
||
|
|
|
||
|
|
if (!formData || formData.length === 0) {
|
||
|
|
throw createError({ statusCode: 400, message: 'No file uploaded' })
|
||
|
|
}
|
||
|
|
|
||
|
|
const fileField = formData.find(f => f.name === 'file')
|
||
|
|
|
||
|
|
if (!fileField || !fileField.data) {
|
||
|
|
throw createError({ statusCode: 400, message: 'No file data' })
|
||
|
|
}
|
||
|
|
|
||
|
|
const ext = fileField.filename ? fileField.filename.toLowerCase().slice(fileField.filename.lastIndexOf('.')) : ''
|
||
|
|
|
||
|
|
if (!allowedExtensions.includes(ext)) {
|
||
|
|
throw createError({ statusCode: 400, message: `File type not allowed. Allowed: ${allowedExtensions.join(', ')}` })
|
||
|
|
}
|
||
|
|
|
||
|
|
const filename = fileField.filename ? sanitizeFilename(fileField.filename) : `upload${ext}`
|
||
|
|
const filePath = join(folderPath, filename)
|
||
|
|
|
||
|
|
writeFileSync(filePath, fileField.data)
|
||
|
|
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
filename,
|
||
|
|
url: `/${folder}/${filename}`
|
||
|
|
}
|
||
|
|
})
|