diff --git a/src/api/controllers/v1/path.controller.js b/src/api/controllers/v1/path.controller.js index 1c13e3b..710f8f5 100644 --- a/src/api/controllers/v1/path.controller.js +++ b/src/api/controllers/v1/path.controller.js @@ -1,9 +1,11 @@ /* eslint-disable import/no-extraneous-dependencies */ // import httpStatus from 'http-status'; import fs from 'fs'; -import archiver from 'archiver'; +import { exec } from 'child_process'; +import sequelize from 'sequelize'; import multer from 'multer'; import path from 'path'; +import { cloneDeep } from 'lodash'; import { handler as ErrorHandel } from '../../middlewares/errors'; // import ApiException from '../../../common/utils/APIException'; import { @@ -12,8 +14,25 @@ import { storage as storageConfig } from '../../../config/vars'; import uploadAdapter from '../../../common/services/adapters/upload-adapter'; -import { cloneDeep, forEach } from 'lodash'; +import File from '../../../common/models/file.model'; + +function getAllFilesWithInfo(dirPath, fileList = []) { + const files = fs.readdirSync(dirPath); + + files.forEach(file => { + const filePath = path.join(dirPath, file); + const stat = fs.statSync(filePath); + + if (stat.isDirectory()) { + getAllFilesWithInfo(filePath, fileList); + } else { + fileList.push({ path: filePath, name: file }); + } + }); + + return fileList; +} function deleteFolderRecursive(folderPath) { if (fs.existsSync(folderPath)) { fs.readdirSync(folderPath).forEach((file) => { @@ -36,46 +55,63 @@ exports.get = (req, res, next) => { try { const user = req.user; - let path = `${storageConfig.uri}/${user.id}`; + let pathDefault = `${storageConfig.uri}/${user.id}`; if (req.body.path) { - path += req.body.path; + pathDefault += req.body.path; } // console.log(path); - const listFile = []; - fs.readdir(path, (err, files) => { + + fs.readdir(pathDefault, async (err, files) => { + let listFile = []; + const listPath = []; if (files && files.length > 0) { files.forEach((item) => { + let pathDb = `${storageConfig.uri}/${user.id}`; + let pathReplace = `${cdnConfig.uri}/${user.id}`; + if (req.body.path === '') { + pathDb += `/${item}`; + pathReplace += `/${item}`; + } else { + pathDb += `${req.body.path}/${item}`; + + pathReplace += `${req.body.path}/${item}`; + } listFile.push({ name: item, - path: `${cdnConfig.uri}/${user.id}${req.body.path}/${item}`, + path: pathReplace, + path_origin: pathDb, isFolder: fs.lstatSync(`${storageConfig.uri}/${user.id}/${req.body.path}/${item}`).isDirectory() }); + if (!fs.lstatSync(pathDb).isDirectory()) { + listPath.push(pathDb); + } }); } + const result = await File.findAll({ where: { + url: { + [sequelize.Op.in]: listPath + } + } }); + listFile = listFile.map((file) => { + const operation = file; + const exist = result.find((a) => a.dataValues.url === file.path_origin); + if (exist) { + operation.download_count = exist.download_count; + } else if (!file.isFolder) { + operation.download_count = 0; + } + return operation; + }); + return res.json({ code: 0, data: listFile }); }); - // test local - // fs.readdir(path, (err, files) => { - // if (files && files.length > 0) { - // files.forEach((item) => { - // listFile.push({ - // name: item, - // path: `${storageConfig.uri}/${user.id}${req.body.path}/${item}`, - // isFolder: fs.lstatSync(`${storageConfig.uri}/${user.id}/${req.body.path}/${item}`).isDirectory() - // }); - // }); - // } - // return res.json({ - // code: 0, - // data: listFile - // }); - // }); + // console.log(listPath); - return null; + // return null; /** resize image uploaded */ } catch (ex) { return ErrorHandel(ex, req, res, next); @@ -90,12 +126,12 @@ exports.get = (req, res, next) => { exports.create = (req, res, next) => { const user = req.user; let dir = `${user.id}`; - const name_folder = cloneDeep(req.body.name).trim(); + const nameFolder = cloneDeep(req.body.name).trim(); if (req.body.path) { dir += req.body.path; } if (req.body.name) { - dir += `/${name_folder}`; + dir += `/${nameFolder}`; } if (!fs.existsSync(dir)) { uploadAdapter.createFolder({ path: dir }); @@ -113,11 +149,26 @@ exports.update = (req, res, next) => { const oldPath = req.body.oldPath.replace(cdnConfig.uri, storageConfig.uri); const newPath = req.body.newPath.replace(cdnConfig.uri, storageConfig.uri); - fs.rename(oldPath, newPath, (err) => { + fs.rename(oldPath, newPath, async (err) => { if (err) { console.log(err); return res.status(400).json({ code: 400, message: 'lỗi' }); } + await File.update( + // Update data + { + url: sequelize.literal(`REPLACE(url, '${oldPath}', '${newPath}')`), + }, + // Options for the update query + { + where: { + url: { + [sequelize.Op.like]: `%${oldPath}%`, // Find records containing the old substring + }, + }, + } + ); + return res.json({ code: 0, message: 'success' }); }); return null; @@ -132,7 +183,7 @@ exports.delete = (req, res, next) => { const user = req.user; const dir = `${storageConfig.uri_backup}/${user.id}`; multer({ dest: `${dir}` }); - const path = req.body.path.replace(cdnConfig.uri, storageConfig.uri); + const path1 = req.body.path.replace(cdnConfig.uri, storageConfig.uri); const newpath = req.body.path.replace(cdnConfig.uri, storageConfig.uri_backup); // fs.rm(path, { recursive: true }, err => { // if (err) { @@ -140,8 +191,19 @@ exports.delete = (req, res, next) => { // } // return res.json({ code: 0, message: 'success' }); // }); - fs.rename(path, newpath, (err) => { + + fs.rename(path1, newpath, async (err) => { if (err) throw err; + await File.destroy( + // Options for the update query + { + where: { + url: { + [sequelize.Op.like]: `%${path1}%`, // Find records containing the old substring + }, + }, + } + ); return res.json({ code: 0, message: 'success' }); }); return null; @@ -152,41 +214,82 @@ exports.delete = (req, res, next) => { exports.download = async (req, res, next) => { try { const user = req.user; - const namefile = `${user.name}-${Date.now()}.zip`; + const namefile = `${user.name.replace(/\s/g, '')}-${Date.now()}.zip`; const dir = `${storageConfig.uri}/download/${user.id}/${namefile}`; const folder = `${storageConfig.uri}/download/${user.id}`; multer({ dest: `${folder}` }); await deleteFolderRecursive(folder); - const output = fs.createWriteStream(dir); - const archive = archiver('zip', { - zlib: { level: 9 } // Sets the compression level. - }); + let command = ` zip -r ${dir} `; + + // const output = fs.createWriteStream(dir); + // const archive = archiver('zip', { + // zlib: { level: 9 } // Sets the compression level. + // }); - archive.pipe(output); + // archive.pipe(output); + let promise = []; if (req.body.data) { - req.body.data.forEach((e) => { - const path = e.path.replace(cdnConfig.uri, storageConfig.uri).replace(/ /g, '\\ '); - // const path = e.path.replace(cdnConfig.uri, storageConfig.uri); - console.log('path', path); - // const download = path.split("/"); - // download.splice( download.indexOf(`${user.id}`), 0, "download"); - // const final_path = download.join("/"); - if (e.isFolder) { - archive.directory(path, e.name); + req.body.data.forEach(async (e) => { + const path1 = e.path.replace(cdnConfig.uri, storageConfig.uri).replace(/ /g, '\\ '); + const path2 = e.path.replace(cdnConfig.uri, storageConfig.uri); + + if (fs.lstatSync(path2).isDirectory()) { + getAllFilesWithInfo(path2, promise); } else { - archive.file(path, { name: e.name }); + console.log('path', path2); + promise.push({ + name: e.name, + path: path2 + }); } + + + command += `${path1} `; }); + console.log('promise', promise); + promise = promise.map((file) => promise.push( + File.findOne({ + where: { url: file.path }, // Condition to find the record with the specified name + }) + .then(record => { + if (record) { + // Record with the specified name found, increment the download_count by 1 + return record.increment('download_count', { by: 1 }); + } + // Record with the specified name not found, create a new record with the name and download_count of 1 (default value) + return File.create({ url: file.path, download_count: 1, name: file.name }); + }) + .catch(err => { + console.error('Error:', err); + }) + )); } - archive.finalize(); - return res.json({ - code: 0, - data: { - name: namefile, - path: `${cdnConfig.uri}/download/${user.id}/${namefile}`, + exec(command, (error, stdout, stderr) => { + if (error) { + console.error(`Command execution error: ${error.message}`); + return res.status(400).json({ + code: 400, + message: 'error' + }); + } + if (stderr) { + console.error(`Command stderr: ${stderr}`); + return res.status(400).json({ + code: 400, + message: 'error' + }); } + console.log(`Command output: ${stdout}`); + Promise.all(promise); + return res.json({ + code: 0, + data: { + name: namefile, + path: `${cdnConfig.uri}/download/${user.id}/${namefile}`, + } + }); }); } catch (ex) { return ErrorHandel(ex, req, res, next); @@ -196,9 +299,9 @@ exports.download = async (req, res, next) => { exports.forceDelete = (req, res, next) => { try { - const path = req.body.path.replace(cdnConfig.uri, storageConfig.uri); + const path1 = req.body.path.replace(cdnConfig.uri, storageConfig.uri); // const newpath = req.body.path.replace(cdnConfig.uri, storageConfig.uri_backup); - fs.rm(path, { recursive: true }, err => { + fs.rm(path1, { recursive: true }, err => { if (err) { return res.status(400).json({ code: 400, message: 'lỗi', detail: err }); } @@ -218,12 +321,22 @@ exports.deleteMultiple = (req, res, next) => { multer({ dest: `${dir}` }); if (req.body.data) { req.body.data.forEach((e) => { - const path = e.path.replace(cdnConfig.uri, storageConfig.uri); + const path1 = e.path.replace(cdnConfig.uri, storageConfig.uri); let newpath = e.path.replace(cdnConfig.uri, storageConfig.uri_backup); const split = newpath.split('/'); newpath = `${dir}/${split[split.length - 1]}`; - fs.rename(path, newpath, (err) => { + fs.rename(path1, newpath, async (err) => { if (err) throw err; + await File.destroy( + // Options for the update query + { + where: { + url: { + [sequelize.Op.like]: `%${path1}%`, // Find records containing the old substring + }, + }, + } + ); return { code: 0, message: 'success' }; }); });