/** * 文件上传中间件 * * 功能:处理图片上传(如菜品图片、用户头像) * 使用multer库实现文件上传 */ const multer = require('multer'); const path = require('path'); const fs = require('fs'); // 确保上传目录存在 const uploadDir = 'uploads/images'; if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } /** * 配置文件存储 * destination: 文件保存位置 * filename: 文件名生成规则 */ const storage = multer.diskStorage({ // 设置上传文件的存储目录 destination: function (req, file, cb) { cb(null, uploadDir); // null表示没有错误 }, // 设置上传文件的文件名 filename: function (req, file, cb) { // 生成唯一文件名:时间戳-随机数.原扩展名 // 例如:1704873600000-123456.jpg const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); const ext = path.extname(file.originalname); // 获取文件扩展名 cb(null, uniqueSuffix + ext); } }); /** * 文件过滤器 * 只允许上传图片文件 */ const fileFilter = (req, file, cb) => { // 允许的图片MIME类型 const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp']; if (allowedTypes.includes(file.mimetype)) { cb(null, true); // 接受文件 } else { cb(new Error('只能上传图片文件(jpg, jpeg, png, gif, webp)'), false); } }; /** * 创建multer上传实例 */ const upload = multer({ storage: storage, fileFilter: fileFilter, limits: { fileSize: 5 * 1024 * 1024 // 限制文件大小为5MB } }); /** * 单个图片上传中间件 * * 使用示例: * router.post('/dishes', uploadSingle, createDish); * * 前端上传示例(FormData): * const formData = new FormData(); * formData.append('image', file); * axios.post('/dishes', formData); */ const uploadSingle = upload.single('image'); // 'image'是表单字段名 /** * 多个图片上传中间件 * * 使用示例: * router.post('/gallery', uploadMultiple, uploadGallery); * * 前端上传示例: * const formData = new FormData(); * files.forEach(file => { * formData.append('images', file); * }); */ const uploadMultiple = upload.array('images', 10); // 最多10张图片 /** * 删除上传的文件 * @param {string} filename - 文件名 * * 说明:当删除数据库记录时,也要删除对应的图片文件 */ const deleteUploadedFile = (filename) => { try { if (!filename) return; const filePath = path.join(uploadDir, filename); // 检查文件是否存在 if (fs.existsSync(filePath)) { fs.unlinkSync(filePath); // 同步删除文件 console.log(`✅ 已删除文件: ${filename}`); } } catch (error) { console.error('❌ 删除文件失败:', error.message); } }; /** * 获取文件的访问URL * @param {string} filename - 文件名 * @returns {string} 文件URL * * 例如:/uploads/images/1704873600000-123456.jpg */ const getFileUrl = (filename) => { if (!filename) return null; return `/uploads/images/${filename}`; }; /** * 从URL中提取文件名 * @param {string} url - 文件URL * @returns {string} 文件名 */ const getFilenameFromUrl = (url) => { if (!url) return null; return path.basename(url); }; // 导出所有函数 module.exports = { uploadSingle, uploadMultiple, deleteUploadedFile, getFileUrl, getFilenameFromUrl };