Spaces:
Sleeping
Sleeping
| const { execFile } = require('child_process'); | |
| const http = require('http'); | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const formidable = require('formidable'); // Ajout de formidable pour analyser les requêtes multipart/form-data | |
| // Importer dotenv pour gérer les variables d'environnement | |
| require('dotenv').config(); | |
| const { Storage } = require('@google-cloud/storage'); | |
| // Si la variable GOOGLE_APPLICATION_CREDENTIALS n'est pas définie, on la définit ici. | |
| if (!process.env.GOOGLE_APPLICATION_CREDENTIALS) { | |
| process.env.GOOGLE_APPLICATION_CREDENTIALS = path.join(__dirname, 'service-key.json'); | |
| } | |
| // Instancier le client Google Cloud Storage | |
| const storage = new Storage(); | |
| const bucketName = "test3-2d896.appspot.com"; | |
| // Chemin vers le dossier contenant les fichiers statiques | |
| const staticDir = path.join(__dirname, 'public'); | |
| // Fonction pour servir les fichiers statiques | |
| function serveStaticFile(req, res) { | |
| let filePath = path.join(staticDir, req.url === '/' ? 'index.html' : req.url); | |
| // Normalisez le chemin pour éviter des caractères relatifs comme "../" | |
| filePath = path.normalize(filePath); | |
| // Vérifiez que le fichier demandé reste dans le dossier `public` | |
| if (!filePath.startsWith(staticDir)) { | |
| res.writeHead(403, { 'Content-Type': 'text/plain' }); | |
| res.end('Accès refusé'); | |
| return; | |
| } | |
| // Vérifiez si le fichier existe | |
| fs.stat(filePath, (err, stats) => { | |
| if (err || !stats.isFile()) { | |
| res.writeHead(404, { 'Content-Type': 'text/plain' }); | |
| res.end('Fichier non trouvé'); | |
| return; | |
| } | |
| // Détecte le type MIME basé sur l'extension | |
| const ext = path.extname(filePath).toLowerCase(); | |
| const mimeTypes = { | |
| '.html': 'text/html', | |
| '.css': 'text/css', | |
| '.js': 'application/javascript', | |
| '.json': 'application/json', | |
| '.png': 'image/png', | |
| '.jpg': 'image/jpeg', | |
| '.svg': 'image/svg+xml', | |
| '.wasm': 'application/wasm', | |
| }; | |
| const contentType = mimeTypes[ext] || 'application/octet-stream'; | |
| // Lit et sert le fichier | |
| fs.readFile(filePath, (err, data) => { | |
| if (err) { | |
| res.writeHead(500, { 'Content-Type': 'text/plain' }); | |
| res.end('Erreur du serveur'); | |
| return; | |
| } | |
| res.writeHead(200, { 'Content-Type': contentType }); | |
| res.end(data); | |
| }); | |
| }); | |
| } | |
| const server = http.createServer((req, res) => { | |
| // Ajouter les en-têtes CORS nécessaires pour toutes les requêtes | |
| res.setHeader('Access-Control-Allow-Origin', '*'); | |
| res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); | |
| res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); | |
| // Gérer les requêtes OPTIONS (préflight request) | |
| if (req.method === 'OPTIONS') { | |
| res.writeHead(204); | |
| res.end(); | |
| return; | |
| } | |
| // Servir les fichiers statiques pour les requêtes GET | |
| if (req.method === 'GET') { | |
| serveStaticFile(req, res); | |
| return; | |
| } | |
| // Endpoint : Création des données JSON pour une visite | |
| if (req.method === 'POST' && req.url === '/create-visite-data') { | |
| const bucketName = "test3-2d896.appspot.com"; | |
| const form = new formidable.IncomingForm(); | |
| form.parse(req, async (err, fields) => { | |
| if (err) { | |
| console.error('Erreur lors de l\'analyse de la requête :', err); | |
| res.writeHead(400, { 'Content-Type': 'text/plain' }); | |
| res.end('Erreur lors de l\'analyse de la requête.'); | |
| return; | |
| } | |
| try { | |
| console.log('Métadonnées brutes reçues :', fields.metadata); // Log des données brutes | |
| const metadata = JSON.parse(fields.metadata || '{}'); // Parse en JSON | |
| console.log('Métadonnées analysées :', metadata); | |
| } catch (parseError) { | |
| console.error('Erreur lors du parsing JSON :', parseError); | |
| res.writeHead(400, { 'Content-Type': 'text/plain' }); | |
| res.end('Erreur dans le format du JSON envoyé.'); | |
| } | |
| }); | |
| return; | |
| } | |
| if (req.method === 'POST' && req.url === '/upload-to-gcs') { | |
| let body = ''; | |
| req.on('data', chunk => { | |
| body += chunk.toString(); // Convertir les chunks en chaîne | |
| }); | |
| req.on('end', () => { | |
| try { | |
| // Analysez le corps de la requête en JSON | |
| const { folderPath, jsonData } = JSON.parse(body); | |
| // Loguer le chemin du dossier et les données pour voir ce qui est reçu | |
| console.log('Chemin du dossier:', folderPath); | |
| console.log('Données JSON:', JSON.stringify(jsonData, null, 2)); | |
| // Chemin vers le script local_script.js | |
| const scriptPath = path.resolve(__dirname, 'local_script.js'); // Utilisez path.resolve pour obtenir un chemin absolu | |
| console.log(`Chemin absolu du script : ${scriptPath}`); | |
| // Exécuter le script Node.js avec les paramètres appropriés | |
| const args = [folderPath, JSON.stringify(jsonData)]; | |
| console.log(`Commande exécutée : node ${scriptPath} ${args.join(' ')}`); // Affichez la commande exécutée pour vérification | |
| // Augmentez maxBuffer si nécessaire pour éviter les problèmes liés à la taille des logs | |
| execFile('node', [scriptPath, ...args], { maxBuffer: 1024 * 1024 * 50 }, (error, stdout, stderr) => { | |
| if (error) { | |
| console.error(`Erreur lors de l'exécution de local_script.js :`, error); | |
| console.error(`stderr:`, stderr); | |
| res.writeHead(500, { 'Content-Type': 'text/plain' }); | |
| res.end('Erreur lors du téléversement.'); | |
| return; // Sortir pour éviter un double envoi | |
| } else { | |
| console.log(`Téléversement réussi : ${stdout}`); | |
| res.writeHead(200, { 'Content-Type': 'text/plain' }); | |
| res.end('Fichier téléversé avec succès vers Google Cloud Storage.'); | |
| } | |
| }); | |
| } catch (parseError) { | |
| console.error('Erreur lors de la lecture du corps de la requête:', parseError); | |
| res.writeHead(400, { 'Content-Type': 'text/plain' }); | |
| res.end('Erreur de format du corps de la requête.'); | |
| } | |
| }); | |
| return; // Sortir après avoir traité cette route | |
| } | |
| if (req.method === 'POST' && req.url === '/create-visit') { | |
| const form = new formidable.IncomingForm(); | |
| form.multiples = true; | |
| form.uploadDir = './uploads'; | |
| if (!fs.existsSync(form.uploadDir)) { | |
| fs.mkdirSync(form.uploadDir, { recursive: true }); | |
| } | |
| const bucketName = "test3-2d896.appspot.com"; | |
| form.parse(req, async (err, fields, files) => { | |
| if (err) { | |
| console.error('Erreur lors de l\'analyse de la requête :', err); | |
| res.writeHead(400, { 'Content-Type': 'text/plain' }); | |
| res.end('Erreur lors de l\'analyse de la requête.'); | |
| return; | |
| } | |
| try { | |
| const metadata = JSON.parse(fields.metadata || '{}'); | |
| const { jsonData } = metadata; | |
| console.log('Données JSON reçues :', jsonData); | |
| const folderName = jsonData.folderName; | |
| if (!folderName) { | |
| throw new Error("Nom de dossier (folderName) manquant ou incorrect."); | |
| } | |
| console.log('Nom du dossier pour les fichiers téléversés :', folderName); | |
| const uploadedFiles = Array.isArray(files.files) ? files.files : [files.files]; | |
| const uploadedUrls = []; | |
| for (const file of uploadedFiles) { | |
| const destinationPath = `${folderName}/${file.originalFilename}`; | |
| console.log(`Téléversement du fichier : ${destinationPath}`); | |
| await storage.bucket(bucketName).upload(file.filepath, { | |
| destination: destinationPath, | |
| metadata: { | |
| contentType: file.mimetype, | |
| }, | |
| }); | |
| uploadedUrls.push(`https://storage.googleapis.com/${bucketName}/${destinationPath}`); | |
| } | |
| jsonData.mediaUrls = uploadedUrls; | |
| const jsonFilePath = `${folderName}/visit_data.json`; | |
| const jsonBuffer = Buffer.from(JSON.stringify(jsonData, null, 2)); | |
| console.log(`Téléversement du fichier JSON : ${jsonFilePath}`); | |
| await storage.bucket(bucketName).file(jsonFilePath).save(jsonBuffer, { | |
| contentType: 'application/json', | |
| }); | |
| console.log('Fichiers et données téléversés avec succès.'); | |
| res.writeHead(200, { 'Content-Type': 'application/json' }); | |
| res.end(JSON.stringify({ | |
| success: true, | |
| message: 'Données de la visite téléversées avec succès.', | |
| jsonFilePath, | |
| })); | |
| } catch (error) { | |
| console.error('Erreur lors du traitement des données :', error); | |
| res.writeHead(500, { 'Content-Type': 'text/plain' }); | |
| res.end('Erreur lors du traitement des données.'); | |
| } | |
| }); | |
| return; | |
| } | |
| // Route pour générer une URL signée | |
| if (req.method === 'POST' && req.url === '/generate-signed-url') { | |
| let body = ''; | |
| req.on('data', chunk => { | |
| body += chunk.toString(); | |
| }); | |
| req.on('end', async () => { | |
| try { | |
| // Extraire le `dirUrl` du corps de la requête | |
| const { dirUrl } = JSON.parse(body); | |
| if (!dirUrl) { | |
| res.writeHead(400, { 'Content-Type': 'text/plain' }); | |
| res.end('dirUrl est manquant'); | |
| return; | |
| } | |
| // Nettoyer les segments relatifs du chemin avant de générer l'URL signée | |
| const cleanedDirUrl = dirUrl.replace(/\/?\.\.\//g, ''); | |
| const bucketName = 'test3-2d896.appspot.com'; | |
| const filePath = `users/visite_3D/${cleanedDirUrl}`; // Utiliser le chemin nettoyé sans encodage | |
| const options = { | |
| version: 'v4', | |
| action: 'read', | |
| expires: Date.now() + 15 * 60 * 1000, // URL valable pour 15 minutes | |
| }; | |
| // Générer une URL signée (GCS s'occupe de l'encodage) | |
| const [url] = await storage.bucket(bucketName).file(filePath).getSignedUrl(options); | |
| console.log(`URL signée générée : ${url}`); | |
| // Répondre avec l'URL signée | |
| res.writeHead(200, { 'Content-Type': 'application/json' }); | |
| res.end(JSON.stringify({ url })); | |
| } catch (error) { | |
| console.error('Erreur lors de la génération de l\'URL signée:', error); | |
| res.writeHead(500, { 'Content-Type': 'text/plain' }); | |
| res.end('Erreur lors de la génération de l\'URL signée.'); | |
| } | |
| }); | |
| return; | |
| } | |
| // Nouvelle route pour obtenir le GCS token | |
| if (req.method === 'GET' && req.url === '/get-gcs-token') { | |
| try { | |
| // Générez ou récupérez le token GCS ici | |
| const gcsToken = '9be5e912-95e8-4e13-841e-8be3bf99505d'; // Remplacez cela par la méthode de génération dynamique si nécessaire | |
| // Répondre avec le token | |
| res.writeHead(200, { 'Content-Type': 'application/json' }); | |
| res.end(JSON.stringify({ token: gcsToken })); | |
| } catch (error) { | |
| console.error('Erreur lors de la récupération du jeton GCS:', error); | |
| res.writeHead(500, { 'Content-Type': 'text/plain' }); | |
| res.end('Erreur lors de la récupération du jeton GCS.'); | |
| } | |
| return; | |
| } | |
| // Si aucune des routes n'est trouvée, envoyer une réponse 404 | |
| res.writeHead(404, { 'Content-Type': 'text/plain' }); | |
| res.end('Route non trouvée'); | |
| }); | |
| server.listen(7860, () => { | |
| console.log('Serveur en écoute sur le port 7860'); | |
| }); | |