const express = require('express'); const multer = require('multer'); const path = require('path'); const fs = require('fs'); const dbConnector = require('../utils/dbConnector'); const { asyncHandler } = require('../middlewares/errorHandler'); const router = express.Router(); // 配置multer用于文件上传 const storage = multer.diskStorage({ destination: (req, file, cb) => { const uploadType = req.body.type || 'common'; const uploadDir = path.join(__dirname, `../uploads/${uploadType}`); // 确保上传目录存在 if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } cb(null, uploadDir); }, filename: (req, file, cb) => { const uploadType = req.body.type || 'common'; const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); const ext = path.extname(file.originalname); const filename = `${uploadType}_${uniqueSuffix}${ext}`; cb(null, filename); } }); const upload = multer({ storage: storage, limits: { fileSize: 10 * 1024 * 1024, // 10MB限制 }, fileFilter: (req, file, cb) => { // 允许所有文件类型 cb(null, true); } }); /** * 文件上传接口 * POST /api/v1/upload */ router.post('/', upload.single('file'), asyncHandler(async (req, res) => { if (!req.file) { return res.status(400).json({ code: 400, message: '请选择要上传的文件' }); } const uploadType = req.body.type || 'common'; const userId = req.user?.id; // 构建文件访问URL const fileUrl = `/uploads/${uploadType}/${req.file.filename}`; // 保存文件记录到数据库(可选) if (userId) { try { await dbConnector.query( `INSERT INTO uploads (user_id, filename, original_name, file_type, file_size, file_url, upload_type, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, NOW())`, [ userId, req.file.filename, req.file.originalname, req.file.mimetype, req.file.size, fileUrl, uploadType ] ); } catch (error) { console.warn('保存文件记录失败:', error); // 不中断上传流程,仅记录警告 } } res.json({ code: 200, message: '上传成功', data: { url: fileUrl, filename: req.file.filename, original_name: req.file.originalname, size: req.file.size, mime_type: req.file.mimetype, upload_type: uploadType } }); })); /** * 获取上传文件列表 * GET /api/v1/upload */ router.get('/', asyncHandler(async (req, res) => { const userId = req.user.id; const { page = 1, limit = 10, type } = req.query; const offset = (page - 1) * limit; let query = 'SELECT * FROM uploads WHERE user_id = ?'; let queryParams = [userId]; if (type) { query += ' AND upload_type = ?'; queryParams.push(type); } query += ' ORDER BY created_at DESC LIMIT ? OFFSET ?'; queryParams.push(parseInt(limit), parseInt(offset)); const files = await dbConnector.query(query, queryParams); const countResult = await dbConnector.query( 'SELECT COUNT(*) as count FROM uploads WHERE user_id = ?' + (type ? ' AND upload_type = ?' : ''), type ? [userId, type] : [userId] ); const total = countResult[0].count; res.json({ code: 200, message: '获取成功', data: { files: files, pagination: { page: parseInt(page), limit: parseInt(limit), total: total, pages: Math.ceil(total / limit) } } }); })); /** * 删除上传文件 * DELETE /api/v1/upload/:id */ router.delete('/:id', asyncHandler(async (req, res) => { const { id } = req.params; const userId = req.user.id; // 查询文件信息 const file = await dbConnector.query( 'SELECT * FROM uploads WHERE id = ? AND user_id = ?', [id, userId] ); if (file.length === 0) { return res.status(404).json({ code: 404, message: '文件不存在' }); } // 删除物理文件 const filePath = path.join(__dirname, `../${file[0].file_url}`); if (fs.existsSync(filePath)) { fs.unlinkSync(filePath); } // 删除数据库记录 await dbConnector.query( 'DELETE FROM uploads WHERE id = ? AND user_id = ?', [id, userId] ); res.json({ code: 200, message: '删除成功' }); })); module.exports = router;