--- title: "Configurar el backend de su aplicación" url: https://docs.catalyst.zoho.com/es/tutorials/photo-store-app/nodejs/config-backend/ description: "Cree una aplicación de galería React para cargar imágenes en un bucket en Stratus y compartir estas imágenes con otros usuarios registrados. Aloje la aplicación en AppSail, sincronícela con GitHub y despliéguela usando Pipelines." last_updated: 2026-08-17T12:16:04Z service: All Services type: tutorial related_links: - name: "Catalyst Stratus" url: /es/cloud-scale/help/stratus/introduction/ - name: "Catalyst AppSail" url: /es/serverless/help/appsail/introduction/ - name: "SDK de Stratus para Node.js" url: /es/sdk/nodejs/v2/cloud-scale/stratus/overview/ - name: "API REST de Stratus" url: /es/api/code-reference/cloud-scale/stratus/get-all-buckets/#GetAllBuckets --- # Configurar el backend de su aplicación En este paso, va a configurar la lógica del backend requerida para la aplicación. Antes de comenzar a agregar código, necesita instalar los siguientes paquetes para asegurar que todas las dependencias requeridas se cumplan. Navegue a la carpeta server presente en el directorio `PhotoStoreApp/server` e instale los siguientes paquetes usando el comando que se muestra a continuación: - **Express**: El paquete [`express`](https://www.npmjs.com/package/express) es necesario para manejar solicitudes HTTP. - **Sharp**: El paquete [`sharp`](https://www.npmjs.com/package/sharp) es necesario para mostrar las imágenes cargadas en varios tamaños, incluyendo miniaturas en la aplicación. - **Multer**: El paquete [`multer`](https://www.npmjs.com/package/multer) es necesario para manejar la carga de archivos en aplicaciones Express. - [**SDK de Catalyst**](https://docs.catalyst.zoho.com/es/sdk/nodejs/v2/overview/): Para usar los métodos del SDK requeridos en el servicio AppSail. ```sh npm install express path zcatalyst-sdk-node@3.0.0-beta.3 multer sharp ``` ![catalyst_tutorials_photostore_stratus_install_backend_pack](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_install_backend_pack.webp) Ahora agregará código a los siguientes archivos para implementar la lógica del backend requerida. Agregaremos código a los siguientes archivos presentes en la carpeta server en el directorio `PhotoStoreApp/server/`: - `index.js`: Este archivo contendrá las APIs requeridas para implementar varias funcionalidades de la aplicación, como convertir las imágenes a miniaturas, obtener todas las imágenes y obtener todas las imágenes compartidas. - `helperfunction.js`: Este archivo contiene las funciones auxiliares necesarias para completar los procesos detallados en el archivo `index.js`. La siguiente tabla ilustra la lógica del backend de esta aplicación.
Funcionalidad de la aplicación APIs presentes en `index.js` Funciones presentes en `helperfunction.js`
Redimensionar y cargar imágenes como miniaturas `/convertToThumbnailAndUpload` `uploadToStratus()`
Obtener las imágenes requeridas del bucket `/fetchAllImages` `listMyObjects()`
Obtener solo las imágenes compartidas `/getSharedImages` `listSharedObjects()` `listMyObjects()`
Copie el código a continuación y péguelo en los archivos respectivos de su proyecto usando un IDE y guarde los archivos. > **Nota:** Revise el código en esta sección para asegurarse de comprenderlo completamente. **index.js** ```js 'use strict'; const express = require('express'); const path = require('path'); let catalyst = require('zcatalyst-sdk-node'); const multer = require("multer"); const helperFunctions = require('./helper-functions'); const app = express(); const appDir = path.join(__dirname, '../photo-store-app'); const port = process.env.X_ZOHO_CATALYST_LISTEN_PORT || 9000; app.use(express.json()); app.use(express.static(appDir)); const upload = multer({ dest: "uploads/" }); app.get('/', function (req, res) { res.sendFile(path.join(appDir, 'index.html')); }); app.post("/convertToThumbnailAndUpload", upload.single("image"), async (req, res) => { try { const obj = catalyst.initialize(req, { scope: 'admin' }); const stratus = obj.stratus(); const bucket = stratus.bucket("YOUR_BUCKET_NAME"); const thumbnailName = req.file.originalname.substring(0, req.file.originalname.lastIndexOf(".")); const inputPath = req.file.path; const zuid = req.body.id; console.log("ID: " + zuid); const thumbnailPath = `photos/thumbnails/${zuid}/`; let result; await helperFunctions.uploadToStratus(bucket, inputPath, thumbnailPath, thumbnailName) .then(resp => { console.log("Success"); result = resp; res.json({ message: "Thumbnail created and uploaded successfully" }); }) .catch(error => { console.error("Error: " + JSON.stringify(error.message)); res.status(500).json({ message: "Error Occurred" }); return; }); } catch (error) { console.log("Error in convertToThumbnailAndUpload API: " + error.message); } }); app.get("/fetchAllImages", async (req, res) => { try { const obj = catalyst.initialize(req); const zuid = req.query.id; console.log("ID: " + zuid); const objPath = "photos/" + zuid; const stratus = obj.stratus(); const bucket = stratus.bucket("YOUR_BUCKET_NAME"); let resp = await helperFunctions.listMyObjects(bucket, objPath); res.json(resp); } catch (error) { console.error("Error at fetchAllImages API... ", error.message); res.status(500).send({ error: "An error occurred while fetching images." }); } }); app.get('/getAllUsers', async (req, res) => { try { const app = catalyst.initialize(req, { scope: "user" }); const appAdmin = catalyst.initialize(req, { scope: "admin" }); const userManagementAdmin = appAdmin.userManagement(); const userManagements = app.userManagement(); let allUserPromise = userManagementAdmin.getAllUsers(); let currentUserPromise = userManagements.getCurrentUser(); let details; let currentUser; await allUserPromise.then(allUserDetails => { details = allUserDetails; }).catch(err => { console.log("Error: " + err.message); }); await currentUserPromise.then(details => { currentUser = details.email_id; }).catch(err => { console.log("Error: " + err.message); }); const userDetails = details.map(id => ({ zuid: id.zuid, mailId: id.email_id, name: id.first_name })); const otherUsers = userDetails.filter(user => user.mailId !== currentUser); res.send(otherUsers); } catch (error) { console.error("Error in getAllUsers API: " + JSON.stringify(error.message)); res.status(500).send({ error: "An error occurred while fetching details." }); } }); app.post('/shareDetails', async (req, res) => { try { const app = catalyst.initialize(req); let zcql = app.zcql(); let query = `SELECT COUNT(ImageShareDetails.BucketPath) FROM ImageShareDetails WHERE BucketPath = '${req.body.imagePath}' AND UserZuid = '${req.body.zuid}'`; let result = await zcql.executeZCQLQuery(query); let isPresent = result[0].ImageShareDetails["COUNT(BucketPath)"]; if (isPresent == 0) { let rowData = { UserName: req.body.userName, BucketPath: req.body.imagePath, UserZuid: req.body.zuid, IsUpdate: req.body.isUpdate, SharedBy: req.body.sharedBy }; let datastore = app.datastore(); let table = datastore.table('ImageShareDetails'); let insertPromise = table.insertRow(rowData); insertPromise.then((row) => { console.log("Inserted Row: " + row); }).catch((err) => { console.error("Error: " + err.message); }); res.json({ message: "Access Provided" }); } else { res.json({ message: "Image Already Shared" }); } } catch (error) { console.error("Error in shareDetails API: " + error.message); res.status(500).send({ message: "Error Occurred" }); } }); app.get('/getSharedImages', async (req, res) => { try { const obj = catalyst.initialize(req); const zuid = req.query.id; const objPath = "photos/" + zuid; const stratus = obj.stratus(); const bucket = stratus.bucket("YOUR_BUCKET_NAME"); const zcql = obj.zcql(); let resp = await helperFunctions.listSharedObjects(bucket, objPath, zcql, zuid); res.json(resp); } catch (error) { console.error("Error in getSharedImages API: " + error.message); res.status(500).json({ message: "Error Occurred" }); } }); app.get('/getSharedDetails', async (req, res) => { try { const obj = catalyst.initialize(req); const zuid = req.query.id; let zcql = obj.zcql(); let query = `SELECT * FROM ImageShareDetails WHERE SharedBy = '${zuid}'`; let data = await zcql.executeZCQLQuery(query); const result = data.map(item => ({ UserName: item.ImageShareDetails.UserName, IsUpdate: item.ImageShareDetails.IsUpdate, BucketPath: item.ImageShareDetails.BucketPath, UserId: item.ImageShareDetails.UserZuid })); res.send(result); } catch (error) { console.error("Error in getSharedDetails API: " + error.message); res.status(500).json({ message: "Error Occurred" }); } }); app.patch('/updateSharedDetails', async (req, res) => { try { const obj = catalyst.initialize(req); const isRevoke = req.body.RevokeAccess; const zuid = req.body.UserId; const isUpdate = req.body.IsUpdate; const bucketPath = req.body.BucketPath; let zcql = obj.zcql(); let query; if (isRevoke == "yes") { query = `DELETE FROM ImageShareDetails WHERE UserZuid = '${zuid}' AND BucketPath = '${bucketPath}'`; } else { query = `UPDATE ImageShareDetails SET IsUpdate = ${isUpdate} WHERE UserZuid = '${zuid}' AND BucketPath = '${bucketPath}'`; } let data = await zcql.executeZCQLQuery(query); res.json({ message: "Updated Successfully" }); } catch (error) { console.error("Error in updateSharedDetails API: " + error); res.status(500).json({ message: "Error Occurred" }); } }); app.listen(port, () => { console.log(`Example app listening on port ${port}`); }); ``` > **Nota:** Asegúrese de proporcionar el nombre de su bucket en las líneas **20**, **49** y **127**. **helper-function.js** ```js const sharp = require("sharp"); async function listMyObjects(bucket, prefix, isEdit = true) { try { const objects = await bucket.listPagedObjects({ prefix: prefix }); let result = []; for (let i = 0; i < objects.contents.length; i++) { const objDetails = JSON.parse(objects.contents[i]); const imgInfo = { key: objDetails.key, object_url: objDetails.object_url, isEditAccess: isEdit }; result.push(imgInfo); } return result; } catch (error) { console.error("Error at listMyObjects function: " + error); } } async function uploadToStratus(bucket, inputPath, thumbnailPath, thumbnailName) { try { const streamData = await sharp(inputPath) .resize({ width: 150, height: 150 }) .toFormat("jpeg", { quality: 70 }) .toBuffer(); const result = await bucket.putObject( thumbnailPath + thumbnailName + ".jpeg", streamData ); console.log("uploadToStratus method Completed"); return result; } catch (error) { console.error("Error Occurred..." + JSON.stringify(error)); throw { message: "Error in uploading", code: 500 }; } } async function listSharedObjects(bucket, prefix, zcql, zuid) { try { let query = `SELECT * FROM ImageShareDetails WHERE UserZuid = ${zuid}`; let result = await zcql.executeZCQLQuery(query); const queryData = result.map(item => ({ path: item.ImageShareDetails.BucketPath, isEdit: item.ImageShareDetails.IsUpdate })); let allSharedImages = []; for (const item of queryData) { const result = await listMyObjects(bucket, item.path, item.isEdit); allSharedImages.push(result); } return allSharedImages; } catch (error) { console.error("Error Occurred..." + error.message); } } module.exports = { listMyObjects, uploadToStratus, listSharedObjects }; ```