update router getType
All checks were successful
Deploy to Production / deploy (push) Successful in 21s
All checks were successful
Deploy to Production / deploy (push) Successful in 21s
This commit is contained in:
@@ -16,6 +16,7 @@ class GameTypeController {
|
||||
const cacheKey = `game_types:list:${page}:${limit}:${is_active || 'all'}:${is_premium || 'all'}:${difficulty_level || 'all'}`;
|
||||
|
||||
const cached = await cacheUtils.get(cacheKey);
|
||||
/*
|
||||
if (cached) {
|
||||
return res.json({
|
||||
success: true,
|
||||
@@ -23,6 +24,7 @@ class GameTypeController {
|
||||
cached: true,
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
const where = {};
|
||||
if (is_active !== undefined) where.is_active = is_active === 'true';
|
||||
|
||||
@@ -263,12 +263,6 @@ class TeacherController {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
jobId: job.id,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get teacher datatypes
|
||||
|
||||
276
controllers/uploadController.js
Normal file
276
controllers/uploadController.js
Normal file
@@ -0,0 +1,276 @@
|
||||
const multer = require('multer');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
/**
|
||||
* Upload Controller - Quản lý upload file
|
||||
*/
|
||||
class UploadController {
|
||||
constructor() {
|
||||
// Danh sách các extension cho từng loại file
|
||||
this.imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg', '.ico'];
|
||||
this.audioExtensions = ['.mp3', '.wav', '.ogg', '.m4a', '.aac', '.flac', '.wma'];
|
||||
this.videoExtensions = ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv', '.webm'];
|
||||
|
||||
// Tạo các thư mục nếu chưa tồn tại
|
||||
this.ensureDirectories();
|
||||
|
||||
// Cấu hình multer storage
|
||||
this.storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
const fileExt = path.extname(file.originalname).toLowerCase();
|
||||
let uploadPath = 'public/files';
|
||||
|
||||
if (this.imageExtensions.includes(fileExt)) {
|
||||
uploadPath = 'public/images';
|
||||
} else if (this.audioExtensions.includes(fileExt) || this.videoExtensions.includes(fileExt)) {
|
||||
uploadPath = 'public/media';
|
||||
}
|
||||
|
||||
cb(null, uploadPath);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
// Tạo tên file unique: timestamp-random-originalname
|
||||
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
|
||||
const ext = path.extname(file.originalname);
|
||||
const nameWithoutExt = path.basename(file.originalname, ext);
|
||||
const sanitizedName = nameWithoutExt.replace(/[^a-zA-Z0-9]/g, '_');
|
||||
cb(null, `${sanitizedName}-${uniqueSuffix}${ext}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Cấu hình multer với giới hạn kích thước
|
||||
this.upload = multer({
|
||||
storage: this.storage,
|
||||
limits: {
|
||||
fileSize: 50 * 1024 * 1024, // 50MB max file size
|
||||
},
|
||||
fileFilter: (req, file, cb) => {
|
||||
// Cho phép tất cả các loại file
|
||||
cb(null, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Đảm bảo các thư mục upload tồn tại
|
||||
*/
|
||||
ensureDirectories() {
|
||||
const directories = [
|
||||
'public/images',
|
||||
'public/media',
|
||||
'public/files'
|
||||
];
|
||||
|
||||
directories.forEach(dir => {
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload single file
|
||||
*/
|
||||
uploadSingle(req, res, next) {
|
||||
const uploadHandler = this.upload.single('file');
|
||||
|
||||
uploadHandler(req, res, (err) => {
|
||||
if (err instanceof multer.MulterError) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Upload error',
|
||||
error: err.message,
|
||||
});
|
||||
} else if (err) {
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: 'Server error during upload',
|
||||
error: err.message,
|
||||
});
|
||||
}
|
||||
|
||||
if (!req.file) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'No file uploaded',
|
||||
});
|
||||
}
|
||||
|
||||
// Xác định loại file
|
||||
const fileExt = path.extname(req.file.originalname).toLowerCase();
|
||||
let fileType = 'file';
|
||||
|
||||
if (this.imageExtensions.includes(fileExt)) {
|
||||
fileType = 'image';
|
||||
} else if (this.audioExtensions.includes(fileExt)) {
|
||||
fileType = 'audio';
|
||||
} else if (this.videoExtensions.includes(fileExt)) {
|
||||
fileType = 'video';
|
||||
}
|
||||
|
||||
// Tạo URL truy cập file
|
||||
const fileUrl = `/${req.file.path.replace(/\\/g, '/')}`;
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'File uploaded successfully',
|
||||
data: {
|
||||
filename: req.file.filename,
|
||||
originalname: req.file.originalname,
|
||||
mimetype: req.file.mimetype,
|
||||
size: req.file.size,
|
||||
type: fileType,
|
||||
path: req.file.path,
|
||||
url: fileUrl,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload multiple files
|
||||
*/
|
||||
uploadMultiple(req, res, next) {
|
||||
const uploadHandler = this.upload.array('files', 10); // Max 10 files
|
||||
|
||||
uploadHandler(req, res, (err) => {
|
||||
if (err instanceof multer.MulterError) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Upload error',
|
||||
error: err.message,
|
||||
});
|
||||
} else if (err) {
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: 'Server error during upload',
|
||||
error: err.message,
|
||||
});
|
||||
}
|
||||
|
||||
if (!req.files || req.files.length === 0) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'No files uploaded',
|
||||
});
|
||||
}
|
||||
|
||||
const uploadedFiles = req.files.map(file => {
|
||||
const fileExt = path.extname(file.originalname).toLowerCase();
|
||||
let fileType = 'file';
|
||||
|
||||
if (this.imageExtensions.includes(fileExt)) {
|
||||
fileType = 'image';
|
||||
} else if (this.audioExtensions.includes(fileExt)) {
|
||||
fileType = 'audio';
|
||||
} else if (this.videoExtensions.includes(fileExt)) {
|
||||
fileType = 'video';
|
||||
}
|
||||
|
||||
const fileUrl = `/${file.path.replace(/\\/g, '/')}`;
|
||||
|
||||
return {
|
||||
filename: file.filename,
|
||||
originalname: file.originalname,
|
||||
mimetype: file.mimetype,
|
||||
size: file.size,
|
||||
type: fileType,
|
||||
path: file.path,
|
||||
url: fileUrl,
|
||||
};
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: `${uploadedFiles.length} files uploaded successfully`,
|
||||
data: uploadedFiles,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file
|
||||
*/
|
||||
async deleteFile(req, res, next) {
|
||||
try {
|
||||
const { filepath } = req.body;
|
||||
|
||||
if (!filepath) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Filepath is required',
|
||||
});
|
||||
}
|
||||
|
||||
// Kiểm tra file có tồn tại không
|
||||
if (!fs.existsSync(filepath)) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'File not found',
|
||||
});
|
||||
}
|
||||
|
||||
// Xóa file
|
||||
fs.unlinkSync(filepath);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'File deleted successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file info
|
||||
*/
|
||||
async getFileInfo(req, res, next) {
|
||||
try {
|
||||
const { filepath } = req.query;
|
||||
|
||||
if (!filepath) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Filepath is required',
|
||||
});
|
||||
}
|
||||
|
||||
// Kiểm tra file có tồn tại không
|
||||
if (!fs.existsSync(filepath)) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'File not found',
|
||||
});
|
||||
}
|
||||
|
||||
const stats = fs.statSync(filepath);
|
||||
const fileExt = path.extname(filepath).toLowerCase();
|
||||
let fileType = 'file';
|
||||
|
||||
if (this.imageExtensions.includes(fileExt)) {
|
||||
fileType = 'image';
|
||||
} else if (this.audioExtensions.includes(fileExt)) {
|
||||
fileType = 'audio';
|
||||
} else if (this.videoExtensions.includes(fileExt)) {
|
||||
fileType = 'video';
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
path: filepath,
|
||||
size: stats.size,
|
||||
type: fileType,
|
||||
created: stats.birthtime,
|
||||
modified: stats.mtime,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new UploadController();
|
||||
Reference in New Issue
Block a user