--- title: "アプリケーションのバックエンドを設定する" url: https://docs.catalyst.zoho.com/ja/tutorials/photo-store-app/nodejs/config-backend/ description: "Stratusのバケットに画像をアップロードし、他の登録ユーザーとこれらの画像を共有するReactギャラリーアプリを構築します。AppSailでアプリをホストし、GitHubと同期してPipelinesを使用してアプリをデプロイします。" last_updated: 2026-08-17T12:16:04Z service: All Services type: tutorial related_links: - name: "Catalyst Stratus" url: /ja/cloud-scale/help/stratus/introduction/ - name: "Catalyst AppSail" url: /ja/serverless/help/appsail/introduction/ - name: "Stratus Node.js SDK" url: /ja/sdk/nodejs/v2/cloud-scale/stratus/overview/ - name: "Stratus REST API" url: /ja/api/code-reference/cloud-scale/stratus/get-all-buckets/#GetAllBuckets --- # アプリケーションのバックエンドを設定する このステップでは、アプリケーションに必要なバックエンドロジックを設定します。 コードの追加を開始する前に、必要な依存関係がすべて満たされるように、以下のパッケージをインストールする必要があります。 `PhotoStoreApp/server`ディレクトリにあるserverフォルダに移動し、以下に示すコマンドを使用して次のパッケージをインストールします: - **Express**: [`express`](https://www.npmjs.com/package/express)パッケージは、HTTPリクエストを処理するために必要です。 - **Sharp**: [`sharp`](https://www.npmjs.com/package/sharp)パッケージは、アップロードされた画像をサムネイルを含むさまざまなサイズで表示するために必要です。 - **Multer**: [`multer`](https://www.npmjs.com/package/multer)パッケージは、Expressアプリケーションでファイルアップロードを処理するために必要です。 - [**Catalyst SDK**](https://docs.catalyst.zoho.com/ja/sdk/nodejs/v2/overview/): AppSailサービスで必要なSDKメソッドを使用するために必要です。 ```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) 次に、必要なバックエンドロジックを実装するために、以下のファイルにコードを追加します。 `PhotoStoreApp/server/`ディレクトリのserverフォルダにある以下のファイルにコードを追加します: - `index.js`: このファイルには、画像のサムネイル変換、すべての画像の取得、すべての共有画像の取得など、さまざまなアプリケーション機能を実装するために必要なAPIが含まれます。 - `helperfunction.js`: このファイルには、`index.js`ファイルで詳述されているプロセスを完了するために必要なヘルパー関数が含まれます。 以下の表は、このアプリケーションのバックエンドロジックを示しています。
アプリケーション機能 `index.js`に含まれるAPI `helperfunction.js`に含まれる関数
画像をリサイズしてサムネイルとしてアップロード `/convertToThumbnailAndUpload` `uploadToStratus()`
バケットから必要な画像を取得 `/fetchAllImages` `listMyObjects()`
共有画像のみを取得 `/getSharedImages` `listSharedObjects()` `listMyObjects()`
以下のコードをコピーして、IDEを使用してプロジェクトのそれぞれのファイルに貼り付け、ファイルを保存してください。 > **注:** このセクションのコードを確認して、十分に理解していることを確認してください。 **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}`); }); ``` > **注:** **20**行目、**49**行目、**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 }; ```