banatie-service/apps/api-service/src/middleware/upload.ts

89 lines
2.6 KiB
TypeScript

import multer from 'multer';
import { Request, RequestHandler } from 'express';
// Configure multer for memory storage (we'll process files in memory)
const storage = multer.memoryStorage();
// File filter for image types only
const fileFilter = (_req: Request, file: Express.Multer.File, cb: multer.FileFilterCallback) => {
const allowedTypes = ['image/png', 'image/jpeg', 'image/jpg', 'image/webp'];
if (allowedTypes.includes(file.mimetype)) {
console.log(
`[${new Date().toISOString()}] Accepted file: ${file.originalname} (${file.mimetype})`,
);
cb(null, true);
} else {
console.log(
`[${new Date().toISOString()}] Rejected file: ${file.originalname} (${file.mimetype})`,
);
cb(new Error(`Unsupported file type: ${file.mimetype}. Allowed: PNG, JPEG, WebP`));
}
};
// Configuration constants
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
const MAX_FILES = 3;
// Configure multer with limits and file filtering
export const upload = multer({
storage,
limits: {
fileSize: MAX_FILE_SIZE, // 5MB per file
files: MAX_FILES, // Maximum 3 files
},
fileFilter,
});
// Middleware for handling reference images
export const uploadReferenceImages: RequestHandler = upload.array('referenceImages', MAX_FILES);
// Error handler for multer errors
export const handleUploadErrors = (error: any, _req: Request, res: any, next: any) => {
if (error instanceof multer.MulterError) {
const timestamp = new Date().toISOString();
console.error(`[${timestamp}] Multer error:`, error.message);
switch (error.code) {
case 'LIMIT_FILE_SIZE':
return res.status(400).json({
success: false,
error: `File too large. Maximum size: ${MAX_FILE_SIZE / (1024 * 1024)}MB`,
message: 'File upload failed',
});
case 'LIMIT_FILE_COUNT':
return res.status(400).json({
success: false,
error: `Too many files. Maximum: ${MAX_FILES} files`,
message: 'File upload failed',
});
case 'LIMIT_UNEXPECTED_FILE':
return res.status(400).json({
success: false,
error: 'Unexpected file field. Use "referenceImages" for image uploads',
message: 'File upload failed',
});
default:
return res.status(400).json({
success: false,
error: error.message,
message: 'File upload failed',
});
}
}
if (error.message.includes('Unsupported file type')) {
return res.status(400).json({
success: false,
error: error.message,
message: 'File validation failed',
});
}
// Pass other errors to the next error handler
next(error);
};