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
209 lines
6.3 KiB
JavaScript
209 lines
6.3 KiB
JavaScript
// 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; |