IBM Cloud Docs
开发 Web 应用程序

开发 Web 应用程序

本教程向您展示了如何使用 IBM Cloud® Object Storage来构建简单的图像库,从而将许多不同的概念和实践密钥汇集到 Web 开发中。

从头至尾构建 Web 应用程序涵盖许多不同的概念,非常适合用于了解 IBM Cloud Object Storage 的功能。 应用程序将 IBM Cloud Object Storage 用于存储在允许用户上载和查看 JPEG 图像文件的 Node.js 应用程序中。

场景

本教程的方案涉及许多移动部件:

  • 用于托管 Web 应用程序的 Web 服务器
  • 使用命令行
  • 库中图像的存储实例
  • 集成到持续交付中的版本控制系统
  • 脚本和标记中的客户机端应用程序绑定
  • 要上载和显示的图像

如果您要在一个包中查找所有这些内容,那么本教程将为您提供一个完整的从头到尾的示例。 但是,此指令只能暂时搁置安全和安全代码的原则。 实际投入生产的 Web 应用程序需要适当的安全性,否则它们将不适合可能的访问者。

准备工作

确保您具有需要启动的内容:

  • IBM Cloud Platform 的帐户
  • Docker(作为 IBM Cloud Developer Tools 的一部分)
  • Node.js
  • Git(桌面版和命令行版)

使用命令行

首先,打开有经验的开发者都熟悉,并且新手也能轻松上手的工具:命令行。 对于许多用户,图形用户界面 (GUI) 将计算机的命令行界面降级为二级状态。 但是现在,是时候将其带回来了 (尽管 GUI 不会很快消失,尤其是当您需要浏览 Web 以下载命令行工具集的指示信息时)。

打开 shell 并创建目录。 将您自己的参考目录更改为您创建的新目录。 创建后,您的应用程序将拥有自己的子目录,其中包含启动和运行所需的启动代码和配置。

离开命令行并返回到浏览器,以便您可以遵循指示信息在链接处安装 IBM Cloud Platform 开发者工具。 Developer Tools为构建和部署云应用程序提供了可扩展和可重复的方法。

安装 Docker

使用容器 (例如 Docker) 可加速开发,简化测试并支持自动化部署。 容器是一种轻量级结构,它不需要操作系统,只需要你的代码和从依赖关系到设置的所有配置。

Docker 作为 Developer Tools的一部分进行安装,您需要它。 其工作主要在用于构建新应用程序的例程中的后台进行。 Docker 必须处于运行中,构建命令才会有效。 在 "Docker中枢在线创建 "Docker账户,运行 "Docker应用程序并登录。

安装 Node.js

您构建的应用程序使用 Node.JS作为服务器端引擎来运行此网络应用程序的JavaScript代码。 要使用Node包管理器(npm)管理应用程序的依赖关系,必须在本地安装Node。 此外,Node 的本地安装简化了测试,加快了开发速度。

在开始之前,可以考虑使用版本管理器 (例如,Node 版本管理器或 nvm) 来安装 Node。 版本管理器降低了管理不同版本的 Node.js的复杂性。

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash

...或 "wget(只需一个,但不能两个都用;使用系统中可用的任何一个):

wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash

或者,对于 Windows,您可以使用 "nvm 进行 Windows安装,安装程序和源代码请参见链接。

使用 nvm 安装 Node。

nvm install v6.17.1

无论您在计算机上安装 Node.js 和 npm (包含在 Node中) 后使用哪种方法,都祝贺您自己顺利开始了工作!

安装 Git

您可能已经熟悉 Git,因为它是最广泛使用的源代码版本控制系统。 之后,当您在“IBM Cloud平台中创建用于持续交付和部署的持续部署(CD)工具链时,就会使用”Git。 如果您没有GitHub账户,请在 GitHub 网站上创建一个免费的公共个人账户;否则,请使用您可能拥有的任何其他账户登录。

您需要生成 SSH 密钥并将其上载到 GitHub 概要文件,以便从命令行安全地访问 GitHub。 但是,现在执行此操作提供了良好的实践,因为您稍后将对用于 IBM Cloud Platform 的 GitHub 实例重复这些步骤。

现在,下载 GitHub Desktop 并运行安装程序。 安装程序完成后,使用您的帐户登录到 GitHub。

输入对存储库的任何落实的名称和电子邮件 (这将公开显示)。 将应用程序链接到您的帐户后,可能会要求您通过 GitHub 帐户在线验证应用程序连接。

'GitHub桌面登录窗口
github_desktop_setup

创建 Node.js 入门模板应用程序

要开始在本地开发应用程序,首先要从命令行直接登录IBM Cloud平台。平台,如示例所示。 您可以指定可选参数,例如具有选项 -o 的组织和具有选项 -s 的空间。 如果使用联合账户,请使用 "--sso

ibmcloud login

按如下所示输入命令,以下载并安装本教程中使用的 CLI 扩展。

ibmcloud cf install

登录时,可能会要求您选择区域。 对于本练习,请选择 us-south 作为区域,因为该选项用于在本教程的后续部分中构建 CD 工具链。

接下来,设置端点 (如果尚未设置)。 其他端点是可能的,并且可能是生产用途的首选端点。 现在,使用显示的代码 (如果适合您的帐户)。

ibmcloud api cloud.ibm.com

接下来,创建 Web 应用程序。 dev 空间是组织的缺省选项,但您可能希望创建其他空间以隔离不同的工作。 例如,将“金融”与“开发”分开。

ibmcloud dev create

有了这个命令,你就会被问到一系列问题。 您可以在过程中的许多点返回,因此如果您感到丢失,那么可以通过删除现有目录并创建新目录来重新开始。 即使在命令行上创建应用程序,您仍会在 IBM Cloud 控制台中看到结果。

请注意用于创建“Web 应用程序”的选项。 这才是你想要的。

===============================================================================
Select an application type:

 1. Backend Service / Web App
 2. Mobile App
-------------------------
 0. Exit

===============================================================================
? Enter selection number:> 1

提供了许多选项,但您需要 "Node"。 请输入“4”,然后按 Enter 键。

===============================================================================
Select a language:

 1. Go
 2. Java - MicroProfile / Java EE
 3. Java - Spring
 4. Node
 5. Python - Django
 6. Python - Flask
 7. Swift
-------------------------
 0. Return to the previous selection

===============================================================================
? Enter selection number:> 4

在对编程语言和框架进行选择之后,下一个选择将有这么多选项,它可能会滚动通过您想要的服务。 如示例中所示,您希望将简单 Node.js Web 应用程序与 Express.js配合使用。输入 "3" 并按 Enter 键。

===============================================================================
Select a Starter Kit:

APPSERVICE
-------------------------------------------------------------------------------

 1. Node-RED - A starter to run the Node-RED open-source project on
    IBM Cloud.

 2. Node.js + Cloudant - A web application with Node.js and Cloudant

 3. Node.js Express App - Start building your next Node.js Express
    app on IBM Cloud.


WATSON
-------------------------------------------------------------------------------

 4. Natural Language Understanding Node.js App - Use Watson Natural
    Language Understanding to analyze text to help you understand its
    concepts, entities, keywords, sentiment, and more.

 5. Speech to Text Node.js App - React app using the Watson Speech to
    Text service to transform voice audio into written text.

 6. Text to Speech Node.js App - React app using the Watson Text to
    Speech service to transform text into audio.

 7. Visual Recognition Node.js App - React app using the Watson
    Visual Recognition service to analyze images for scenes, objects, text,
    and other subjects.

-------------------------
 0. Return to the previous selection

===============================================================================
? Enter selection number:> 3

对于各地的开发者来说,仍然需要最难的选项: 命名您的应用程序。 遵循示例并输入 webapplication,然后按 Enter 键。

? Enter a name for your application> webapplication

之后,您可以根据需要或意愿,通过网络控制台添加更多服务,如数据存储或计算功能。 但是,当系统询问您是否要立即添加服务时,请输入 "n" 作为“否”。 另外,如果尚未设置资源组,那么此时可能会提示您。 您可以通过在此提示符处输入 "n" 来跳过此操作。

Using the resource group Default (default) of your account

? Do you want to select a service to add to this application? [Y/n]> n

管理容器化应用程序的一种方法是使用编排软件,如Kubernetes,它是开发中的_事实标准_。

键入 "4 "并按回车键,即可使用IBM DevOps'将 CD 集成到项目生命周期中。

===============================================================================
Select from the following DevOps toolchain and target runtime environment
options:

 1. IBM DevOps, deploy to Knative-based Kubernetes containers
 2. IBM DevOps, deploy to Helm-based Kubernetes containers
 3. IBM DevOps, deploy to Helm-based Red Hat OpenShift containers
 4. No DevOps, with manual deployment

===============================================================================
? Enter selection number:> 4

您必须为自动化部署 CD 工具链选择区域。 选择引用先前选择的相同区域的选项 "5"。

--------------------------------------------------------------------------------
Select a region for your toolchain from the following options:
--------------------------------------------------------------------------------
 1. eu-de (Frankfurt)
 2. eu-gb (London)
 3. jp-tok
 4. us-east (Washington DC)
 5. us-south (Dallas)
--------------------------------------------------------------------------------
 0. Return to the previous selection
--------------------------------------------------------------------------------
? Enter selection number:> 5

生成新应用程序会提醒我们,用于部署应用程序的工具链需要一些其他配置。 As mentioned earlier, uploading your public key to GitHub (at the CD Toolchain instance on the IBM Cloud Platform), is required to deliver the deployed application by using GitHub.

Note: For successful connection to the DevOps toolchain, this machine
must be configured for SSH access to your IBM Cloud GitLab account at
https://git.cloud.ibm.com/profile/keys in order to download the
application code.

进一步的提示会确认您之前定义的应用程序和工具链名称。 该示例展示了如何根据需要更改主机和工具链名称。 主机名对于应用程序的服务端点必须是唯一的,但如果不存在冲突,您只需在要求确认时按返回即可。

The DevOps toolchain for this app will be: webapplication
? Press [Enter] to accept this, or enter a new value now>


The hostname for this app will be: webapplication
? Press [Enter] to accept this, or enter a new value now>

The app webapplication has been created in IBM Cloud.

DevOps toolchain created at
https://cloud.ibm.com/devops/toolchains/6ffb568a-e48f-4e27-aed0-00ca931dde66?env_id=ibm:yp:us-south

如果复制并粘贴 ibmcloud dev create 命令返回的链接,那么还可以访问 CD 工具链。 如果您错过了捕捉链接,可以稍后从控制台访问。 随着此过程继续在线创建应用程序条目以及包含样本代码的目录,将提供更多信息。

Cloning repository
https://git.cloud.ibm.com/Organization.Name/webapplication...
Cloning into 'webapplication'...
remote: Counting objects: 60, done.
remote: Compressing objects: 100% (54/54), done.
remote: Total 60 (delta 4), reused 0 (delta 0)
Receiving objects: 100% (60/60), 50.04 KiB | 1.52 MiB/s, done.
Resolving deltas: 100% (4/4), done.
OK

The app, webapplication, has been successfully saved into the
current directory.

最后一句话的意思是,如果查看当前目录,现在可以看到一个新的子目录 "webapplication。 此目录包含新的 Node.js 应用程序的支架。 但是,虽然可能存在食谱,但食材本身仍包装在 Docker 映像中,并且必须进行组合。 安装完成后,Docker会在本地计算机上运行,但如果需要重启,请按此操作。 如果在不运行 Docker 的情况下构建新的 Web 应用程序失败,但这不是唯一可能的错误。 如果遇到问题,请查看错误信息,其中可能包含相应链接,可在在线门户中查看IBM Cloud的结果日志。平台账户的在线门户中查看结果日志的相应链接。

ibmcloud dev build

现在已构建应用程序,您可以使用 run 命令在本地运行代码。 完成后,将提供的 URL 复制并粘贴到浏览器地址栏中,通常为 "http://localhost:3000

ibmcloud dev run

既然已创建并定义了应用程序,接下来请查看应用程序以确认它是否工作正常。 如果你看到图 2 所示的占位符图像,那就大功告成了! 您创建了一个新的Node.js网络应用程序,并准备将其部署到云中。

新的 'Node.js应用程序!
初始节点应用程序

Deploy the app to IBM Cloud Platform with the deploy command (as shown in the example).

ibmcloud dev deploy

ibmcloud dev deploy 将根据您先前指定的区域端点和主机名再次显示该 URL。 您可以在 IBM Cloud Platform 上查看存储在门户网站中的日志的链接。 请接着访问云中的新 Web 应用程序!

创建“Web 展示区”应用程序

让我们回顾一下在IBM Cloud上开发Node.js应用程序所需的先决条件。平台。 您已创建了 IBM Cloud Platform 帐户,并且安装了 Developer Tools(已用于安装 Docker)。 然后,安装了 Node.js。作为本教程的先决条件列出的最后一项是 Git,您现在可以深入了解它。

我们将在 Node.js中开始处理图像库的具体操作。现在,请将 GitHub Desktop 用于此场景,但您也可以使用 Git 命令行客户机来完成相同的任务。 要开始使用,请克隆一个新网络应用程序的启动模板。

遵循以下过程:

  1. 在此处下载样本: download。 使用浏览器将应用程序模板下载到本地开发环境。 与其从“IBM Cloud平台克隆示例应用程序,不如使用示例中的命令获取”IBM Cloud Object StorageWeb Gallery 应用程序的启动模板。 克隆存储库后,在 COS-WebGalleryStart 目录中可找到该入门模板应用程序。 打开 Git CMD 窗口,并切换到要在其中克隆 Github 存储库的目录。 一旦出现,请使用本教程的第一个示例中显示的命令来开始添加新文件。

    curl images/image-gallery-tutorial.zip -o image-gallery-tutorial.zip
    
  2. 在本地运行应用程序。 打开终端并将工作目录切换到 COS-WebGalleryStart directory。 请注意 package.json 文件中列出的 Node.js 依赖关系。 使用下面显示的命令将它们下载到位。

    npm install
    
  3. 使用显示的命令运行应用程序。

    npm start
    

    打开浏览器,通过输出到控制台的地址和端口 "http://localhost:3000 查看应用程序。

    要在本地重启应用程序,请杀死节点进程(Ctrl+C)使其停止,然后再次使用 "npm start。 使用 nodemon 将在应用程序检测到更改时重新启动该应用程序,并为您节省时间。 像这样在全局安装 'nodemon npm install -g nodemon. 在应用程序目录下使用命令行运行它:nodemon,启动应用程序。

  4. 开始准备应用程序以进行部署! 将COS-WebGallery,文件 "manifest.yml 中的应用程序名称属性值更新为您在IBM Cloud上输入的应用程序名称。平台上输入的名称,如有必要,还可更新示例中显示的其他信息。 应用程序的 manifest.yml 类似于以下示例。 您可以自定义应用程序根目录中的 "package.json 文件,并在其中写入应用程序名称和作者姓名。

    applications:
    - path: .
      memory: 256M
      instances: 1
      domain: us-south.cf.appdomain.cloud
      name: webapplication
      host: webapplication
      disk_quota: 1024M
      random-route: true
    

    现在,你可能需要设置 SSH 密钥,以交互方式向远程源推送代码。 如果你为 SSH 密钥设置了口令,那么每次将更改推送到版本库的远程源时,都需要输入该密码。

  5. 删除“webapplication 目录的内容,并用你修改过的”COS-WebGalleryStart 目录的内容取而代之。 使用经过细致调整的 Git 技能,添加原先使用 CLI 或 Github Desktop 删除和添加到存储库的文件。 然后,将更改推送到存储库源。 今后,您只需将修改推送到Git,就能对基于云的网络应用程序进行修改。 克隆更改并将其存储到服务器后,CD 工具链将自动重启服务器进程。

实际上,您已经重新编码了应用程序,因此请重复构建过程。 但这次要使用新的图片库代码。

将应用程序部署到 IBM Cloud Platform。

要获取具有 IBM Cloud Platform 更改的入门模板应用程序,请通过重复先前执行的相同步骤,使用 Developer Tools 来部署该应用程序。

  1. 如果尚未登录,或已重启或注销,请使用IBM Cloud平台。使用 "login 命令登录平台。

    ibmcloud login
    
  2. 使用 api 命令为区域设置 API 端点。

    ibmcloud api cloud.ibm.com
    
  3. 使用构建命令(如示例所示)构建应用程序,以交付该应用程序。

    ibmcloud dev build
    
    1. 下面将在本地测试应用程序。 这允许您使用 run 命令在本地运行相同的代码。
    ibmcloud dev run
    
  4. 使用 deploy 命令将应用程序部署到 IBM Cloud Platform。

    ibmcloud dev deploy
    

    代码显示了本示例中用于构建、测试和部署初始网络应用程序的命令序列。

    ibmcloud login --sso
    ibmcloud api cloud.ibm.com
    ibmcloud target --cf
    ibmcloud dev enable
    ibmcloud dev build
    ibmcloud dev run
    ibmcloud dev deploy
    

    进程完成时,IBM Cloud 平台会报告应用程序已上载,成功部署和启动。 如果您还登录了IBM Cloud平台网络控制台,您也会在那里收到应用程序状态的通知。 但是,最重要的是,您可以通过使用浏览器访问 IBM Cloud Platform 报告的应用程序 URL,或者在 Web 控制台中通过单击“查看应用程序”按钮,验证应用程序是否已部署。

    测试应用程序。 您可以看到创建时部署的缺省应用程序模板更改为如下所示的入门模板应用程序,这证明了已将应用程序成功部署到 IBM Cloud Platform。

    查看已部署应用程序的结果。
    '

创建 Git 分支

现在,需要为本地开发环境创建分支,以用于 IBM Cloud Platform Delivery Pipeline 的构建阶段:

  1. 如果使用GitHub桌面,请单击分支图标;系统会提示你输入分支名称。 本例使用 "local-dev 作为名称。

    使用GitHub桌面创建本地开发分支
    ''

  2. 创建分支后,GitHub会将 Local-dev 分支上的本地文件与默认分支仓库中的文件进行比较,并报告“无本地变更”。 现在,可以单击“发布”以将在本地存储库上创建的该分支添加到 GitHub 存储库(如图 5 所示)。

    发布您的 git 分支到您的软件仓库的远程源代码'
    ''

现在,Local-dev 分支已发布到工具链中的GitHub代码库,您的IBM Cloud平台交付管道的构建阶段将被触发,随后您将随时推送提交到部署阶段。平台Delivery Pipeline后,只要推送提交,就会触发部署阶段。 无需通过 CLI 部署应用程序,因为部署已直接集成到工作流程中。

设置存储凭证

您需要为 Web 应用程序配置 Object Storage 凭证,以及将在其中存储和检索图像的“存储区”。 您将创建的 API 密钥需要“Object StorageHMAC 凭据,该凭据由您的”服务证书 定义。 您可能认识“access_key_id 和”secret_access_key 这两个术语,因为您可能拥有一个AWS账户,并使用一个已经包含“aws_access_key_id 和”aws_secret_access_key 条目的凭证文件。

完成创建 API 密钥,下载该密钥,并复制 HMAC 凭证的操作后,请完成以下步骤:

  1. 在本地开发环境上,将凭证放在 Windows 路径 %USERPROFILE%\\.aws\\credentials 中。 对于 Mac/Linux 用户,凭证应进入 ~/.aws/credentials)。 示例显示了典型凭证文件的内容。

    [default]
    aws_access_key_id = {access_key_id}
    aws_secret_access_key = {secret_access_key}
    
  2. 在IBM Cloud上使用 CLI 命令创建的应用程序的网页中平台上使用 CLI 命令创建的应用程序的网页中,登录IBM Cloud将所需凭证定义为环境变量,以符合开发最佳实践。平台,并选择您的应用程序 "webapplication。 从选项卡中单击运行时

  3. 在运行时窗口中,单击页面开头的环境变量,然后滚动到用户定义部分,即可添加变量。

  4. 添加两个变量:一个变量包含 "access_key_id 的值,使用 "AWS_ACCESS_KEY_ID 作为密钥的名称;另一个变量包含秘密访问密钥的值,命名为 "AWS_SECRET_ACCESS_KEY。 应用程序在 Object Storage Platform 上运行时,将使用这些变量及其各自的值向 IBM Cloud 实例进行认证(请参阅图 6)。 完成条目后,单击“保存”,IBM Cloud Platform 将自动重新启动应用程序。

    为应用程序定义的运行时环境变量 '

    '
    ''

接下来,在服务实例的 Object Storage 门户网站中,添加要包含图像的存储区。 此方案使用名为 "web-images 的数据桶。

定制 Node.js IBM Cloud Object Storage 图像库 Web 应用程序

由于此示例使用的是 MVC 体系结构,因此调整项目中的目录结构来反映此体系结构是一种方便的做法,也是最佳实践。 目录结构中的 views 目录包含 EJS 视图模板,routes 目录包含 express routes,而 "controllers 目录则用于放置控制器逻辑。 将这些项目放在名为 "src 的父源代码目录下(见图 7)。

应用程序的源代码结构
目录结构

提示: 先前克隆的存储库包含名为 COS-WebGalleryEnd 的目录。 在执行后续步骤时,在首选编辑器中查看已完成应用程序的源代码可能会很有帮助。 这是您的 "webapplication 版本,将在完成本教程后提交并部署到IBM Cloud平台。平台。

设计应用程序

下面是用户应该能够使用简单图像库 Web 应用程序执行的两个主要任务:

  • 通过 Web 浏览器将图像上传到 Object Storage 存储区。
  • 在 Web 浏览器中查看 Object Storage 存储区中的图像。

后续步骤将重点关注如何完成这两个演示功能,而不是构建已完全开发的生产级应用程序。 部署本教程,然后将其公开并运行意味着任何发现该应用程序的人都可以执行相同的操作:将文件上传到 IBM Cloud Object Storage 存储区,并在其浏览器中查看已存在的任何 JPEG 图像。

开发应用程序

在 "package.json 文件的脚本对象中,你可以看到 "start "是如何定义的。 IBM Cloud Platform 使用此文件来指示节点在每次应用程序启动时运行 app.js。 此外,在本地测试应用程序时也可以使用它。 查看名为 "app.js 的主程序文件。 这是您在使用 "npm start 命令(或 "nodemon 命令)启动应用程序时告诉Node.js首先处理的代码。

{
    "scripts": {
      "start": "node app.js"
    }
}

app.js 文件使用节点来装入入门所需的模块。 Express 框架将应用程序创建为单项,并将其简单地命名为 app。 示例的最后(暂时省略大部分代码)告诉应用程序监听指定的端口和环境属性,或者默认为 3000。 启动成功后,它会在控制台打印一条包含服务器 URL 的信息。

var express = require('express');
var cfenv = require('cfenv');
var bodyParser = require('body-parser');
var app = express();
//...

// start server on the specified port and binding host
var port = process.env.PORT || 3000;
app.listen(port, function() {
    console.log("To view your app, open this link in your browser: http://localhost:" + port);
});
//...

让我们来了解如何定义路径和视图。 第一行代码告诉 Express 框架使用公共目录提供静态文件,其中包括任何静态图片和样式表。 接下来的几行会告诉应用程序在 "src/views 目录中查找视图模板的位置,并将视图引擎设置为 EJS。 此外,该框架还使用 body-parser 中间件将传入的请求数据以 JSON 格式显示给应用程序。 在示例的最后几行,express 应用程序会通过渲染 "index.ejs 视图模板来响应所有传入到应用程序 URL 的 GET 请求。

//...
// serve the files out of ./public as your main files
app.use(express.static('public'));
app.set('views', './src/views');
app.set('view engine', 'ejs');
app.use(bodyParser.json());

var title = 'COS Image Gallery Web Application';
// Serve index.ejs
app.get('/', function (req, res) {
  res.render('index', {status: '', title: title});
});

//...

下图显示了呈现并发送到浏览器时的索引视图模板。 如果您正在使用 nodemon,那么您可能已注意到在保存更改时浏览器已刷新。

通过使用模板和视图显示
''
,您更新了网络应用程序

我们的视图模板在 <head>...</head>; 标记之间共享 HTML 代码,因此您将其放入单独的包含模板中。 该模板(head-inc.ejs)包含一个 scriptlet(JavaScript变量的绑定),用于第 1 行的页面标题。 title 变量在 "app.js 中设置,并在下面一行作为视图模板的数据传入。 否则,您只是在使用一些 CDN 地址来输入 "Bootstrap CSS、"Bootstrap JavaScript 和 "JQuery。 最后,从 pubic/stylesheets 目录添加定制静态 styles.css 文件。

<title><%=title%></title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
      integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
      crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"
        integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
        crossorigin="anonymous">
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
        integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
        crossorigin="anonymous">
</script>

<link rel="stylesheet" href="stylesheets/style.css">

索引视图的主体包含 bootstrap 风格的导航标签和上传表单,其基本布局由 bootstrap 附带的 CSS 样式提供。

请为您的应用程序考虑这两种规格:

  • 在第 24 行将表单方法设为 "POST,表单数据编码类型设为 multipart/form-data。 对于表单操作,将表单中的数据发送到应用程序路由"/"。 稍后,在路由器逻辑中做一些额外的工作,以处理对该路由的 "POST 请求。

  • 向用户显示有关尝试上传文件状态的反馈。 该反馈会通过一个名为 "status "的变量传递给您的视图,并在上传表单后显示。

<!DOCTYPE html>
<html>

<head>
    <%- include('head-inc'); %>
</head>

<body>
<ul class="nav nav-tabs">
    <li role="presentation" class="active"><a href="/">Home</a></li>
    <li role="presentation"><a href="/gallery">Gallery</a></li>
</ul>
<div class="container">
    <h2>Upload Image to IBM Cloud Object Storage</h2>
    <div class="row">
        <div class="col-md-12">
            <div class="container" style="margin-top: 20px;">
                <div class="row">

                    <div class="col-lg-8 col-md-8 well">

                        <p class="wellText">Upload your JPG image file here</p>

                        <form method="post" enctype="multipart/form-data" action="/">
                            <p><input class="wellText" type="file" size="100px" name="img-file" /></p>
                            <br/>
                            <p><input class="btn btn-danger" type="submit" value="Upload" /></p>
                        </form>

                        <br/>
                        <span class="notice"><%=status%></span>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
</body>

</html>

让我们花点时间返回到 app.js。 该示例设置了 Express 路由,以处理应用程序收到的额外请求。 这些路由方法的代码位于项目中 "./src/routes 目录下的两个文件中:

  • imageUploadRoutes.js: 该文件处理用户 选择图片并点击上传时的操作。

  • galleryRoutes.js: This file handles requests when the user clicks the Gallery tab to request the imageGallery view.

//...
var imageUploadRoutes = require('./src/routes/imageUploadRoutes')(title);
var galleryRouter = require('./src/routes/galleryRoutes')(title);

app.use('/gallery', galleryRouter);
app.use('/', imageUploadRoutes);

//...

图像上传

请参阅 imageUploadRoutes.js 中的代码。 您必须创建一个新的 express 路由器实例,并在开始时将其命名为 "imageUploadRoutes。 之后,创建一个返回“imageUploadRoutes 的函数,并将其赋值给一个名为”router 的变量。 完成后,该函数必须作为模块导出,以便框架和 "app.js 中的主代码可以访问。 要将路由逻辑与上传逻辑分开,需要一个名为 "galleryController.js 的控制器文件。 由于该逻辑专门用于处理传入的请求并提供适当的响应,因此应将该逻辑放在该函数中,并将其保存在 "./src/controllers 目录下。

The instance of the Router from the Express framework is where your imageUploadRoutes is designed to route requests for the root app route ("/") when the HTTP POST method is used. Inside the post method of your imageUploadRoutes, use middleware from the multer and multer-s3 modules that is exposed by the galleryController as upload. 中间件从上传表单 "POST 中获取数据和文件,对其进行处理,并运行一个回调函数。 在回调函数中,检查是否获得了 HTTP 状态代码 "200,以及请求对象中是否至少有一个要上传的文件。 根据这些条件,在 "status 变量中设置反馈,并用新状态渲染索引视图模板。

var express = require('express');
var imageUploadRoutes = express.Router();
var status = '';

var router = function(title) {

    var galleryController =
        require('../controllers/galleryController')(title);

    imageUploadRoutes.route('/')
    	.post(
    		galleryController.upload.array('img-file', 1), function (req, res, next) {
                if (res.statusCode === 200 && req.files.length > 0) {
                    status = 'uploaded file successfully';
                }
                else {
                    status = 'upload failed';
                }
                res.render('index', {status: status, title: title});
            });

    return imageUploadRoutes;
};

module.exports = router;

相比之下,"galleryRouter 的代码是简洁的典范。 按照与“imageUploadRouter 相同的模式,在函数的第一行要求输入”galleryController,然后设置路线。 主要区别在于,你是在路由 HTTP“GET 请求,而不是”POST,并在“getGalleryImages 的响应中发送所有输出,这一点在示例最后一行的”galleryController 中有所体现。

var express = require('express');
var galleryRouter = express.Router();

var router = function(title) {

    var galleryController =
        require('../controllers/galleryController')(title);

    galleryRouter.route('/')
        .get(galleryController.getGalleryImages);

    return galleryRouter;
};
module.exports = router;

接下来,查看图库的控制器。

请注意如何设置 multer 上载,这将截断您现在忽略的一些代码。 您需要 "ibm-cos-sdk、"multer“和”multer-s3 模块。 代码显示了如何配置指向 Object Storage 服务器端点的 S3 对象。 为了简单起见,我们会静态设置端点地址、区域和水桶等值,但这些值可以通过环境变量或 JSON 配置文件轻松引用。

通过创建以 storage 作为其唯一属性的新 multer 实例,在 imageUploadRouter 中定义 upload。 该属性告诉“multer 从”multipart/form-data 发送文件的位置。 由于IBM Cloud平台使用S3API 的实现,因此请将存储设置为 "s3-multer 对象。 此 s3-multer 对象包含分配给 s3 对象的 s3 属性。 还有一个 bucket 属性被分配给 myBucket 变量,而该变量又被分配值 web-images。 现在,当“s3-multer 对象从上传表单接收数据时,它就拥有了将文件上传到”Object Storage水桶所需的所有数据。 已上载对象的名称 (或键) 是原始文件名。

使用时间戳记作为文件名的一部分,以保持文件名唯一性。

var galleryController = function(title) {

    var aws = require('ibm-cos-sdk');
    var multer = require('multer');
    var multerS3 = require('multer-s3');

    var ep = new aws.Endpoint('s3.us-south.cloud-object-storage.appdomain.cloud');
    var s3 = new aws.S3({endpoint: ep, region: 'us-south-1'});
    var myBucket = 'web-images';

    var upload = multer({
        storage: multerS3({
            s3: s3,
            bucket: myBucket,
            acl: 'public-read',
            metadata: function (req, file, cb) {
                cb(null, {fieldName: file.fieldname});
            },
            key: function (req, file, cb) {
                console.log(file);
                cb(null, file.originalname);
            }
        })
    });

    var getGalleryImages = function (req, res) { /* ... shown below ... */ };

    return {
        getGalleryImages: getGalleryImages,
        upload: upload
    };
};

module.exports = galleryController;

对于本地测试,一个非常有用的任务是将文件对象显示到控制台:console.log(file)。 对上传表单进行本地测试,并显示控制台日志中的文件输出。

{ fieldname: 'img-file',
originalname: 'Chrysanthemum.jpg',
encoding: '7bit',
mimetype: 'image/jpeg' }

来自回调的反馈声明应用程序在测试时“已成功上载文件”。

成功!
本地测试 1

图像检索和显示

Remember back in app.js, the line of code app.use('/gallery', galleryRouter); tells the express framework to use that router when the /gallery route is requested. 该路由器使用 galleryController.js,定义 getGalleryImages 函数,即您先前见过的特征符。 使用为图片上传函数设置的同一“s3 对象,调用名为”listObjectsV2 的函数。 该函数返回定义数据桶中每个对象的索引数据。 要在 HTML 中显示图像,您需要为 "web-images 桶中的每张 JPEG 图像创建一个图像 URL,以便在视图模板中显示。 由 "listObjectsV2 返回的数据对象闭包中包含有关数据桶中每个对象的元数据。

代码会在 "bucketContents"中循环搜索任何以".jpg "结尾的对象键,并创建一个参数传递给S3的 "getSignedUrl 函数。 如果您提供了对象的邮筒名称和密钥,该函数将返回任何对象的签名 URL。 在回调函数中,将每个 URL 保存在一个数组中,并将其作为名为“imageUrls 的属性的值传递给”HTTP Server响应方法 "res.render"。

//...

    var getGalleryImages = function (req, res) {
        var params = {Bucket: myBucket};
        var imageUrlList = [];

        s3.listObjectsV2(params, function (err, data) {
            if (data) {
                var bucketContents = data.Contents;
                for (var i = 0; i < bucketContents.length; i++) {
                    if (bucketContents[i].Key.search(/.jpg/i) > -1) {
                        var urlParams = {Bucket: myBucket, Key: bucketContents[i].Key};
                        s3.getSignedUrl('getObject', urlParams, function (err, url) {
                            imageUrlList.push(url);
                        });
                    }
                }
            }
            res.render('galleryView', {
                title: title,
                imageUrls: imageUrlList
            });
        });
    };

//...

最后一个代码示例显示了 galleryView 模板的主体以及显示图像所需的代码。 从 res.render() 方法获取 imageUrls 数组,并对一对嵌套的 <div>...</div> 标记进行迭代。 在请求 /gallery 路由时,每个都将发送针对该映像的 GET 请求。

<!DOCTYPE html>
<html>

<head>
    <%- include('head-inc'); %>
</head>

<body>
    <ul class="nav nav-tabs">
        <li role="presentation"><a href="/">Home</a></li>
        <li role="presentation" class="active"><a href="/gallery">Gallery</a></li>
    </ul>
    <div class="container">
        <h2>IBM COS Image Gallery</h2>

        <div class="row">
            <% for (var i=0; i < imageUrls.length; i++) { %>
                <div class="col-md-4">
                    <div class="thumbnail">
                            <img src="<%=imageUrls[i]%>" alt="Lights" style="width:100%">
                    </div>
                </div>
            <% } %>
        </div>
    </div>
</body>

</html>

http://localhost:3000/gallery 本地测试应用程序并查看您的映像。

上传到邮筒的图片已显示
本地测试2

提交到 Git

现在应用程序的基本功能已经正常运行,请将代码提交到本地仓库,然后推送到GitHub。 使用GitHub桌面,单击“更改”(见图 11),在“摘要”字段中输入更改摘要,然后单击“提交到本地-dev”。

已准备好提交到Git的更改
提交更新

单击 同步时,您的落实将发送到远程 local-dev 分支。 此操作将在 Delivery Pipeline中启动构建和部署阶段。

、CDDelivery
、""、"

后续步骤

您从头到尾使用 IBM Cloud Platform 构建了基本 Web 应用程序图像库。 可以在 IBM Cloud Object Storage上进一步探索本基本简介中所涵盖的每个概念。

祝您好运!