BlogEditor/backend/routes/upload.js

93 lines
3.1 KiB
JavaScript

import express from 'express'
import { getPresignedUploadUrl } from '../config/s3.js'
import logger from '../utils/logger.js'
const router = express.Router()
// Get presigned URL for image upload
// Note: authenticateToken middleware is applied at server level
router.post('/presigned-url', async (req, res) => {
try {
const { filename, contentType } = req.body
logger.transaction('GENERATE_PRESIGNED_URL', {
userId: req.user.id,
filename,
contentType
})
if (!filename || !contentType) {
logger.warn('UPLOAD', 'Missing required fields', {
hasFilename: !!filename,
hasContentType: !!contentType
})
return res.status(400).json({ message: 'Filename and content type are required' })
}
// Validate content type
if (!contentType.startsWith('image/')) {
logger.warn('UPLOAD', 'Invalid content type', { contentType })
return res.status(400).json({ message: 'File must be an image' })
}
// Check if AWS credentials are configured
if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY) {
logger.error('UPLOAD', 'AWS credentials not configured', null)
return res.status(500).json({
message: 'AWS S3 is not configured. Please set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in backend .env file.'
})
}
// Support both S3_BUCKET_NAME and AWS_BUCKET_NAME (for compatibility with api-v1)
const bucketName = process.env.S3_BUCKET_NAME || process.env.AWS_BUCKET_NAME
if (!bucketName) {
logger.error('UPLOAD', 'S3 bucket name not configured', null)
return res.status(500).json({
message: 'S3 bucket name is not configured. Please set S3_BUCKET_NAME or AWS_BUCKET_NAME in backend .env file.'
})
}
const startTime = Date.now()
const { uploadUrl, imageUrl, key } = await getPresignedUploadUrl(filename, contentType)
const duration = Date.now() - startTime
logger.s3('PRESIGNED_URL_GENERATED', {
userId: req.user.id,
filename,
key,
duration: `${duration}ms`
})
logger.transaction('GENERATE_PRESIGNED_URL_SUCCESS', {
userId: req.user.id,
key,
duration: `${duration}ms`
})
res.json({
uploadUrl,
imageUrl,
})
} catch (error) {
logger.error('UPLOAD', 'Error generating presigned URL', error)
// Provide more specific error messages
let errorMessage = 'Failed to generate upload URL'
if (error.name === 'InvalidAccessKeyId' || error.name === 'SignatureDoesNotMatch') {
errorMessage = 'Invalid AWS credentials. Please check your AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.'
} else if (error.name === 'NoSuchBucket') {
const bucketName = process.env.S3_BUCKET_NAME || process.env.AWS_BUCKET_NAME
errorMessage = `S3 bucket '${bucketName}' does not exist. Please create it or update S3_BUCKET_NAME/AWS_BUCKET_NAME.`
} else if (error.message) {
errorMessage = error.message
}
res.status(500).json({
message: errorMessage,
error: error.name || 'Unknown error'
})
}
})
export default router