Files
uldp-degree-mangement-system/controllers/uploadController.js
r2xrzh9q2z-lab d1b931d547 first commit
2026-02-02 11:07:09 +07:00

228 lines
8.2 KiB
JavaScript

const path = require('path');
const fs = require('fs');
const jsonHelper = require('../utils/jsonHelper');
// Controller xử lý upload ảnh
const uploadController = {
// Upload ảnh và trả về đường dẫn
uploadImage: async (req, res) => {
try {
if (!req.file) {
return res.status(400).json({ success: false, error: 'No file was uploaded' });
}
// Lấy loại ảnh từ query params
const imageType = req.query.imageType || 'general';
// Tạo đường dẫn tương đối để lưu vào database
const relativePath = `/uploads/${imageType}/${req.file.filename}`;
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
const fullUrl = `${baseUrl}${relativePath}`;
// Kiểm tra nếu file đã tồn tại từ trước
const fileAlreadyExists = req.fileAlreadyExists || false;
// Nếu client yêu cầu cập nhật trực tiếp file JSON (ví dụ activities.json),
// thì đồng bộ camps.image và camps.camp-detail.hero.bgImage
try {
const jsonFile = req.body && req.body.jsonFile;
const campLink = req.body && req.body.campLink;
if (jsonFile && campLink) {
// Đọc JSON và cập nhật camp có link khớp
const jsonFilePath = require('path').join(__dirname, '../data', jsonFile);
const jsonData = jsonHelper.readJsonFile(jsonFilePath);
if (jsonData && Array.isArray(jsonData.camps)) {
// campLink có thể được gửi không có dấu / đầu, chuẩn hóa
const normalizedLink = campLink.startsWith('/') ? campLink : `/${campLink}`;
const camp = jsonData.camps.find(c => (c.link || '').toString() === normalizedLink || (c.link || '').toString() === campLink);
if (camp) {
// Đồng bộ camps.image và camps.camp-detail.hero.bgImage - 2 trường này luôn giống nhau
camp.image = relativePath;
// Đảm bảo camp-detail.hero tồn tại và sync bgImage
if (!camp['camp-detail']) camp['camp-detail'] = {};
if (!camp['camp-detail'].hero) camp['camp-detail'].hero = {};
camp['camp-detail'].hero.bgImage = relativePath;
// Lưu thay đổi
jsonHelper.writeJsonFile(jsonFilePath, jsonData);
}
}
}
} catch (e) {
console.warn('Failed to update JSON file after upload:', e && e.message ? e.message : e);
}
return res.status(200).json({
success: true,
path: relativePath,
url: fullUrl,
reused: fileAlreadyExists,
message: fileAlreadyExists ? 'Using existing file' : 'File uploaded successfully'
});
} catch (error) {
console.error('Error uploading image:', error);
return res.status(500).json({ success: false, error: 'Server error while uploading image' });
}
},
// Cập nhật đường dẫn ảnh trong file JSON
updateImagePath: async (req, res) => {
try {
const { jsonFile, jsonPath, newImagePath } = req.body;
if (!jsonFile || !jsonPath || !newImagePath) {
return res.status(400).json({
success: false,
message: 'Missing required information (jsonFile, jsonPath, newImagePath)'
});
}
// Đọc file JSON
const jsonFilePath = path.join(__dirname, '../data', jsonFile);
const jsonData = jsonHelper.readJsonFile(jsonFilePath);
// Cập nhật đường dẫn ảnh theo jsonPath
// jsonPath có định dạng như "banner.image" hoặc "partners[0].logo"
const pathParts = jsonPath.split('.');
let current = jsonData;
// Duyệt qua các phần của path trừ phần cuối
for (let i = 0; i < pathParts.length - 1; i++) {
const part = pathParts[i];
// Kiểm tra nếu là mảng (ví dụ: partners[0])
if (part.includes('[') && part.includes(']')) {
const arrName = part.substring(0, part.indexOf('['));
const index = parseInt(part.substring(part.indexOf('[') + 1, part.indexOf(']')));
if (!current[arrName] || !Array.isArray(current[arrName])) {
return res.status(400).json({
success: false,
message: `Array ${arrName} not found in data`
});
}
current = current[arrName][index];
} else {
if (!current[part]) {
return res.status(400).json({
success: false,
message: `Property ${part} not found in data`
});
}
current = current[part];
}
}
// Cập nhật giá trị
const lastPart = pathParts[pathParts.length - 1];
current[lastPart] = newImagePath;
// Lưu lại file JSON
jsonHelper.writeJsonFile(jsonFilePath, jsonData);
return res.status(200).json({
success: true,
message: 'Image path updated successfully',
data: { jsonPath, newImagePath }
});
} catch (error) {
console.error('Error updating image path:', error);
return res.status(500).json({ success: false, message: 'Server error while updating image path' });
}
},
// Xóa ảnh
deleteImage: async (req, res) => {
try {
const { imagePath } = req.body;
if (!imagePath) {
return res.status(400).json({ success: false, message: 'Missing image path to delete' });
}
// Chuyển đổi đường dẫn tương đối thành đường dẫn tuyệt đối
const fullPath = path.join(__dirname, '../public', imagePath);
// Kiểm tra xem file có tồn tại không
if (!fs.existsSync(fullPath)) {
return res.status(404).json({ success: false, message: 'Image file not found' });
}
// Xóa file
fs.unlinkSync(fullPath);
return res.status(200).json({
success: true,
message: 'Image deleted successfully',
data: { imagePath }
});
} catch (error) {
console.error('Error deleting image:', error);
return res.status(500).json({ success: false, message: 'Server error while deleting image' });
}
},
// List images in a folder
listImages: async (req, res) => {
try {
const imageType = req.query.imageType || 'general';
const dirPath = path.join(__dirname, '../public/uploads', imageType);
if (!fs.existsSync(dirPath)) {
return res.status(200).json({ success: true, images: [] });
}
const files = fs.readdirSync(dirPath).filter(f => !f.startsWith('.'));
const images = files.map(name => ({
name,
path: `/uploads/${imageType}/${name}`,
url: (process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`) + `/uploads/${imageType}/${name}`
}));
return res.status(200).json({ success: true, images });
} catch (error) {
console.error('Error listing images:', error);
return res.status(500).json({ success: false, error: 'Server error while listing images' });
}
},
// Upload video
uploadVideo: async (req, res) => {
try {
if (!req.file) {
return res.status(400).json({ success: false, error: 'No file was uploaded' });
}
// Kiểm tra loại file
const fileType = req.file.mimetype;
if (!fileType.startsWith('video/')) {
// Xóa file nếu không phải video
fs.unlinkSync(req.file.path);
return res.status(400).json({ success: false, error: 'Uploaded file is not a video' });
}
// Tạo đường dẫn tương đối để lưu vào database
const relativePath = `/uploads/videos/${req.file.filename}`;
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
const fullUrl = `${baseUrl}${relativePath}`;
return res.status(200).json({
success: true,
path: relativePath,
url: fullUrl
});
} catch (error) {
console.error('Error uploading video:', error);
return res.status(500).json({ success: false, error: 'Server error while uploading video' });
}
}
};
module.exports = uploadController;