feat(database): Implement DatabaseManager for managing database structure and initialization
All checks were successful
SSH Backend Deploy / ssh-deploy (push) Successful in 1m51s
All checks were successful
SSH Backend Deploy / ssh-deploy (push) Successful in 1m51s
feat(routes): Add camera, image, measurement, project, and video routes with Swagger documentation feat(services): Create storageService and videoService for file management and video processing fix(errorHandler): Enhance error handling with standardized responses and database operation wrappers
This commit is contained in:
209
src/services/storageService.js
Normal file
209
src/services/storageService.js
Normal file
@@ -0,0 +1,209 @@
|
||||
// src/services/storageService.js
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
const { Buffer } = require('buffer');
|
||||
const config = require('../config');
|
||||
|
||||
/**
|
||||
* Service de gestion du stockage des fichiers
|
||||
*/
|
||||
class StorageService {
|
||||
/**
|
||||
* Crée un dossier s'il n'existe pas déjà
|
||||
* @param {string} dirPath - Chemin du dossier à créer
|
||||
* @returns {Promise<string>} Chemin du dossier créé
|
||||
*/
|
||||
static async createDirectory(dirPath) {
|
||||
try {
|
||||
await fs.access(dirPath);
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
await fs.mkdir(dirPath, { recursive: true });
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return dirPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime un dossier et son contenu
|
||||
* @param {string} dirPath - Chemin du dossier à supprimer
|
||||
*/
|
||||
static async deleteDirectory(dirPath) {
|
||||
try {
|
||||
await fs.access(dirPath);
|
||||
await fs.rm(dirPath, { recursive: true, force: true });
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT') {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cherche toutes les images dans un dossier
|
||||
* @param {string} dirPath - Dossier à scanner
|
||||
* @returns {Promise<Array<string>>} Liste des chemins d'images trouvées
|
||||
*/
|
||||
static async scanImages(dirPath = 'storage') {
|
||||
const basePath = path.join(config.paths.storage, dirPath);
|
||||
let results = [];
|
||||
|
||||
try {
|
||||
await fs.access(basePath);
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
await fs.mkdir(basePath, { recursive: true });
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function scanDirectory(directory) {
|
||||
const files = await fs.readdir(directory);
|
||||
for (const file of files) {
|
||||
const filePath = path.join(directory, file);
|
||||
const stat = await fs.stat(filePath);
|
||||
if (stat.isDirectory()) {
|
||||
await scanDirectory(filePath);
|
||||
} else if (file.endsWith('.jpg')) {
|
||||
results.push(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await scanDirectory(basePath);
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enregistre un contenu dans un fichier
|
||||
* @param {string} filePath - Chemin du fichier
|
||||
* @param {Buffer} content - Contenu à enregistrer
|
||||
*/
|
||||
static async saveFile(filePath, content) {
|
||||
const dirPath = path.dirname(filePath);
|
||||
await this.createDirectory(dirPath);
|
||||
if (Buffer.isBuffer(content)) {
|
||||
await fs.writeFile(filePath, content);
|
||||
} else {
|
||||
throw new Error('Le contenu doit être un buffer');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le contenu d'un fichier
|
||||
* @param {string} filePath - Chemin du fichier
|
||||
* @returns {Promise<Buffer>} Contenu du fichier
|
||||
*/
|
||||
static async getFile(filePath) {
|
||||
return await fs.readFile(filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime un fichier
|
||||
* @param {string} filePath - Chemin du fichier à supprimer
|
||||
* @returns {Promise<string>} Message de confirmation
|
||||
*/
|
||||
static async deleteFile(filePath) {
|
||||
try {
|
||||
await fs.access(filePath);
|
||||
await fs.rm(filePath);
|
||||
return `Fichier ${filePath} supprimé avec succès.`;
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
return `Fichier ${filePath} inexistant.`;
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gestionnaire pour les opérations de projet
|
||||
*/
|
||||
static project = {
|
||||
/**
|
||||
* Crée le répertoire d'un projet
|
||||
* @param {number} projectId - ID du projet
|
||||
*/
|
||||
createProjectDirectory: async function(projectId) {
|
||||
const projectPath = path.join(config.paths.storage, `${projectId}`);
|
||||
await StorageService.createDirectory(projectPath);
|
||||
await StorageService.createDirectory(path.join(projectPath, 'images'));
|
||||
await StorageService.createDirectory(path.join(projectPath, 'videos'));
|
||||
console.log(`[STORAGE] Répertoire créé : ${projectPath}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* Supprime le répertoire d'un projet et son contenu
|
||||
* @param {number} projectId - ID du projet
|
||||
*/
|
||||
deleteProjectDirectory: async function(projectId) {
|
||||
const projectPath = path.join(config.paths.storage, `${projectId}`);
|
||||
await StorageService.deleteDirectory(projectPath);
|
||||
console.log(`[STORAGE] Répertoire supprimé : ${projectPath}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gestionnaire pour les opérations de mesures (images)
|
||||
*/
|
||||
static measurement = {
|
||||
/**
|
||||
* Récupère l'image d'une mesure
|
||||
* @param {number} projectId - ID du projet
|
||||
* @param {number} orderId - ID d'ordre de la mesure
|
||||
* @returns {Promise<Buffer>} Contenu de l'image
|
||||
*/
|
||||
getMeasurementImage: async function(projectId, orderId) {
|
||||
const imagePath = path.join(config.paths.storage, `${projectId}`, 'images', `${orderId}.jpg`);
|
||||
console.log(`[STORAGE] Récupération de l'image : ${imagePath}`);
|
||||
return await StorageService.getFile(imagePath);
|
||||
},
|
||||
|
||||
/**
|
||||
* Enregistre l'image d'une mesure
|
||||
* @param {Object} image - Objet image avec buffer
|
||||
* @param {number} projectId - ID du projet
|
||||
* @param {number} orderId - ID d'ordre de la mesure
|
||||
* @returns {Promise<string>} Chemin de l'image enregistrée
|
||||
*/
|
||||
uploadMeasurementImage: async function(image, projectId, orderId) {
|
||||
const imagePath = path.join(config.paths.storage, `${projectId}`, 'images', `${orderId}.jpg`);
|
||||
console.log(`[STORAGE] Enregistrement de l'image : ${imagePath}`);
|
||||
await StorageService.saveFile(imagePath, image.buffer);
|
||||
return imagePath;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gestionnaire pour les opérations de vidéos
|
||||
*/
|
||||
static video = {
|
||||
/**
|
||||
* Récupère une vidéo
|
||||
* @param {number} projectId - ID du projet
|
||||
* @param {number} videoId - ID de la vidéo
|
||||
* @returns {Promise<Buffer>} Contenu de la vidéo
|
||||
*/
|
||||
getVideo: async function(projectId, videoId) {
|
||||
const videoPath = path.join(config.paths.storage, `${projectId}`, 'videos', `${videoId}.mp4`);
|
||||
console.log(`[STORAGE] Récupération de la vidéo : ${videoPath}`);
|
||||
return await StorageService.getFile(videoPath);
|
||||
},
|
||||
|
||||
/**
|
||||
* Supprime une vidéo
|
||||
* @param {string} videoPath - Chemin de la vidéo à supprimer
|
||||
* @returns {Promise<string>} Message de confirmation
|
||||
*/
|
||||
deleteVideo: async function(videoPath) {
|
||||
console.log(`[STORAGE] Suppression de la vidéo : ${videoPath}`);
|
||||
return await StorageService.deleteFile(videoPath);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = StorageService;
|
||||
Reference in New Issue
Block a user