

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Amazon DCV Web Client SDK 入门
开始使用

 Amazon DCV Web Client SDK 包含一个主 `dcv.js` 文件和一些辅助组件。所有文件都是在一个压缩归档中分发的，可以从 [Amazon DCV 网站](https://download.nice-dcv.com/webclientsdk.html)中下载该归档。

**开始使用 Amazon DCV Web Client SDK**

1. Amazon DCV Web Client SDK 归档已使用安全 GPG 签名进行数字签名。要验证该归档的签名，您必须导入 NICE GPG 密钥。为此，打开一个终端窗口并导入 NICE GPG 密钥。

   ```
   $ wget https://d1uj6qtbmh3dt5.cloudfront.net/NICE-GPG-KEY
   ```

   ```
   $ gpg --import NICE-GPG-KEY
   ```

1.  从 [Amazon DCV 网站](https://download.nice-dcv.com/webclientsdk.html)中下载 **Amazon DCV Web Client SDK 归档**和 **Amazon DCV Web Client SDK 归档签名**。

1. 使用该签名验证 Amazon DCV Web Client SDK 归档的签名。

   ```
   				$ gpg --verify
   				signature_filename.zip.sign
   				archive_filename.zip
   ```

   例如：

   ```
   $ gpg --verify nice-dcv-web-client-sdk-1.10.1-1011.zip.sign nice-dcv-web-client-sdk-1.10.1-1011.zip
   ```

1. 如果签名验证成功，请提取 Amazon DCV Web Client SDK 归档内容，并将提取的目录放置在您的 Web 服务器上。例如：

   ```
   				$ unzip
   				archive_filename.zip
   				-d /
   				path_to
   				/
   				server_directory
   				/
   ```
**重要**  
在 Web 服务器上部署 Amazon DCV Web Client SDK 时，您必须保留文件夹结构。
使用 Amazon DCV Web UI SDK 时，请注意，`DCVViewer`React 组件期望此包中的 EULA.txt 和 third-party-licenses .txt 文件出现在嵌入式 Web 服务器的 URL 路径中。应修改 third-party-licenses .txt 文件，使其还包含 Amazon DCV Web Client SDK 包中相应文件的内容，可能还包括使用用户应用程序使用的库中的任何其他许可信息。

# 连接到 Amazon DCV 服务器并获取第一帧


以下教程说明了如何为自定义 Web 客户端准备 HTML 页面，如何进行身份验证并连接到 Amazon DCV 服务器，以及如何从 Amazon DCV 会话接收流式传输的内容的第一帧。

**Topics**
+ [

## 步骤 1：准备 HTML 页面
](#prep-html)
+ [

## 步骤 2：验证身份、连接并获取第一帧
](#auth-conn)
+ [

## 额外任务：自动创建 HTML 登录表单
](#get-token)

## 步骤 1：准备 HTML 页面


 在您的网页中，您必须加载所需的 JavaScript 模块，并且必须添加一个有效的 `<div>` HTML 元素，该元素必须具有有效的 `id` Amazon DCV Web Client SDK，以便从远程 Amazon DCV 服务器提取内容流。

例如：

```
<!DOCTYPE html>
<html lang="en" style="height: 100%;">
  <head>
    <title>DCV first connection</title>
  </head>
  <body style="height: 100%;">
    <div id="root" style="height: 100%;"></div>
    <div id="dcv-display"></div>
    <script type="module" src="index.js"></script>
  </body>
</html>
```

## 步骤 2：验证身份、连接并获取第一帧


本节说明了如何完成用户身份验证过程，如何连接 Amazon DCV 服务器以及如何从 Amazon DCV 服务器接收第一帧内容。

 首先，从 `index.js` 文件中导入 Amazon DCV Web Client SDK。可以将其作为通用模块定义（UMD）模块导入，如下所示：

```
import "./dcvjs/dcv.js"
```

 否则，从版本开始`1.1.0`，也可以将其作为 ECMAScript 模块 (ESM) 从相应的包中导入，如下所示：

```
import dcv from "./dcvjs/dcv.js"
```

定义用于存储身份验证对象、连接对象和 Amazon DCV 服务器 URL 的变量。

```
let auth,
    connection,
    serverUrl;
```

 在脚本加载时记录 Amazon DCV Web Client SDK 版本，并在页面加载时调用 `main` 函数。

```
console.log("Using Amazon DCV Web Client SDK version " + dcv.version.versionStr);
document.addEventListener('DOMContentLoaded', main);
```

 `main` 函数设置日志级别，并启动身份验证过程。

```
function main () {
  console.log("Setting log level to INFO");
  dcv.setLogLevel(dcv.LogLevel.INFO);

  serverUrl = "https://your-dcv-server-url:port/";

  console.log("Starting authentication with", serverUrl);

  auth = dcv.authenticate(
    serverUrl,
    {
      promptCredentials: onPromptCredentials,
      error: onError,
      success: onSuccess
    }
  );
}
```

 `promptCredentials`、`error` 和 `success` 函数是在身份验证过程中必须定义的必需回调函数。

 如果 Amazon DCV 服务器提示输入凭证，则 `promptCredentials` 回调函数从 Amazon DCV 服务器接收请求的凭证质询。如果 Amazon DCV 服务器配置为使用系统身份验证，您必须提供登录凭证。以下代码示例假设用户名是 `my_dcv_user`，密码是 `my_password`。

 如果身份验证失败，则 `error` 回调函数从 Amazon DCV 服务器收到一个错误对象。

 如果身份验证成功，则 `success` 回调函数收到一个对象对数组，其中包括允许 `my_dcv_user` 用户在 Amazon DCV 服务器上连接到的每个会话的会话 ID（`sessionId`）和授权令牌（`authToken`）。以下代码示例调用 connect 函数，并连接到数组中返回的第一个会话。

**注意**  
在以下代码示例中，将 `MY_DCV_USER` 替换为您自己的用户名，并将 `MY_PASSWORD` 替换为您自己的密码。

```
function onPromptCredentials(auth, challenge) {
  // Let's check if in challege we have a username and password request
  if (challengeHasField(challenge, "username") && challengeHasField(challenge, "password")) {
    auth.sendCredentials({username: MY_DCV_USER, password: MY_PASSWORD})
  } else {
    // Challenge is requesting something else...
  }
}

function challengeHasField(challenge, field) {
  return challenge.requiredCredentials.some(credential => credential.name === field);
}

function onError(auth, error) {
  console.log("Error during the authentication: " + error.message);
}

// We connect to the first session returned
function onSuccess(auth, result) {
  let {sessionId, authToken} = {...result[0]};

  connect(sessionId, authToken);
}
```

 连接到 Amazon DCV 服务器。从 Amazon DCV 服务器收到第一帧时，将调用 `firstFrame` 回调方法。

```
function connect (sessionId, authToken) {
  console.log(sessionId, authToken);

  dcv.connect({
    url: serverUrl,
    sessionId: sessionId,
    authToken: authToken,
    divId: "dcv-display",
    callbacks: {
      firstFrame: () => console.log("First frame received")
    }
  }).then(function (conn) {
    console.log("Connection established!");
    connection= conn;
  }).catch(function (error) {
    console.log("Connection failed with error " + error.message);
  });
}
```

## 额外任务：自动创建 HTML 登录表单


 在调用 `promptCredentials` 回调函数时，将会返回 `challenge` 对象。它包括一个名为 `requiredCredentials` 的属性，该属性是一个对象数组 - Amazon DCV 服务器请求的每个凭证一个对象。每个对象包含请求的凭证的名称和类型。您可以使用 `challenge` 和 `requiredCredentials` 对象自动创建 HTML 登录表单。

以下代码示例说明了如何执行该操作。

```
let form,
    fieldSet;

function submitCredentials (e) {
  var credentials = {};
  fieldSet.childNodes.forEach(input => credentials[input.id] = input.value);
  auth.sendCredentials(credentials);
  e.preventDefault();
}

function createLoginForm () {
  var submitButton = document.createElement("button");

  submitButton.type = "submit";
  submitButton.textContent = "Login";

  form = document.createElement("form");
  fieldSet = document.createElement("fieldset");

  form.onsubmit = submitCredentials;
  form.appendChild(fieldSet);
  form.appendChild(submitButton);

  document.body.appendChild(form);
}

function addInput (name) {
  var type = name === "password" ? "password" : "text";

  var inputField = document.createElement("input");
  inputField.name = name;
  inputField.id = name;
  inputField.placeholder = name;
  inputField.type = type;
  fieldSet.appendChild(inputField);
}

function onPromptCredentials (_, credentialsChallenge) {
  createLoginForm();
  credentialsChallenge.requiredCredentials.forEach(challenge => addInput(challenge.name));
}
```

# 使用 Amazon DCV 特征


Amazon DCV 特征是否可用取决于为 Amazon DCV 会话配置的权限以及客户端 Web 浏览器功能。

 Amazon DCV 会话中提供的特征是由为会话指定的权限管理的。这意味着，即使 Amazon DCV Web Client SDK 支持某个特征，也可能会根据会话管理员定义的权限禁止访问该特征。有关更多信息，请参阅《Amazon DCV 管理员指南》中的[配置 Amazon DCV 授权](https://docs.aws.amazon.com/dcv/latest/adminguide/security-authorization.html)。**

## 了解 featuresUpdate 回调函数


 在 Amazon DCV 会话中的特征的可用性发生变化时，Amazon DCV Web Client SDK 使用您在建立连接时指定的 `featuresUpdate` 回调函数通知您。例如：

```
featuresUpdate: function (connection, list) {
  ...
},
```

 该回调函数仅通知您可用性发生变化的功能。`list` 参数是一个字符串数组，它仅包含更新的功能的名称。例如，如果会话的音频输入功能可用性发生变化，则该参数仅包含 `["audio-in"]`。如果会话的剪贴板复制和粘贴功能的可用性以后发生变化，则该参数仅包含 `["clipboard-copy", "clipboard-paste"]`。

## 处理功能更新


 `featuresUpdate` 回调函数仅通知您一个或多个功能的可用性发生变化。要了解更新了哪些功能，您必须使用 `connection.queryFeature` 方法查询该功能。在收到变化通知后，可以随时执行该操作。该方法返回 `Promise`，它解析为请求的功能的更新状态。`status` 值始终是关联的，并且它具有一个名为 `enabled` 的布尔值（`true` \$1 `false`）属性。某些功能可能在 `status` 值中具有其他属性。如果尚未更新该功能的可用性，则会拒绝该功能。

以下示例代码说明了如何执行该操作。

```
// Connection callback called
function featuresUpdate (_, list) {
  if (list.length > 0) {
    list.forEach((feat) => {
      connection.queryFeature(feat).then(status => console.log(feat, "is", status.enabled)));
    });
  }
}
```

# 使用 Amazon DCV Web UI SDK


 以下教程说明了如何在 Amazon DCV 服务器中进行身份验证，连接到该服务器并渲染 Amazon DCV Web UI SDK 中的 `DCVViewer` React 组件。

**Topics**
+ [

## 先决条件
](#prerequisites)
+ [

## 步骤 1：准备 HTML 页面
](#prep-html-ui)
+ [

## 步骤 2：验证身份、连接并渲染 `DCVViewer` React 组件。
](#auth-conn-render)
+ [

## 从 AWS-UI 更新为 Cloudscape Design 系统
](#updateawsuitocloudscape)

## 先决条件


 您需要安装 `React`、`ReactDOM`、`Cloudscape Design Components React`、`Cloudscape Design Global Styles` 和 `Cloudscape Design Design Tokens`。

```
$ npm i react react-dom @cloudscape-design/components @cloudscape-design/global-styles @cloudscape-design/design-tokens
```

 您还需要下载 `Amazon DCV Web Client SDK`。请参阅[Amazon DCV Web Client SDK 入门](getting-started.md)阅读有关如何执行此操作的 step-by-step指南。

您必须创建一个别名以导入 `dcv` 模块，因为它是 Amazon DCV Web UI SDK 的外部依赖项。例如，如果使用 webpack 捆绑 Web 应用程序，您可以使用 [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealias) 选项，如下所示：

```
const path = require('path');

module.exports = {
  //...
  resolve: {
    alias: {
      dcv: path.resolve('path', 'to', 'dcv.js'),
    },
  },
};
```

如果您使用 rollup 进行捆绑，您可以安装并使用 [@rollup/plugin-alias](https://www.npmjs.com/package/@rollup/plugin-alias)，如下所示：

```
import alias from '@rollup/plugin-alias';
const path = require('path');

module.exports = {
  //...
  plugins: [
    alias({
      entries: [
        { find: 'dcv', replacement: path.resolve('path', 'to', 'dcv.js') },
      ]
    })
  ]
};
```

## 步骤 1：准备 HTML 页面


 在您的网页中，您必须加载所需的 JavaScript 模块，并且应该有一个 `<div>` HTML 元素，该元素的有效`id`位置将呈现应用程序的入口组件。

例如：

```
<!DOCTYPE html>
<html lang="en" style="height: 100%;">
  <head>
    <title>DCV first connection</title>
  </head>
  <body style="height: 100%;">
    <div id="root" style="height: 100%;"></div>
    <script type="module" src="index.js"></script>
  </body>
</html>
```

## 步骤 2：验证身份、连接并渲染 `DCVViewer` React 组件。


 本节说明了如何完成用户身份验证过程，如何连接 Amazon DCV 服务器以及如何渲染 `DCVViewer` React 组件。

 首先，从 `index.js` 文件中导入 `React`、`ReactDOM` 和顶级 `App` 组件。

```
import React from "react";
import ReactDOM from 'react-dom';
import App from './App';
```

渲染应用程序的顶级容器节点。

```
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);
```

 在 `App.js` 文件中，导入 Amazon DCV Web Client SDK（作为 ESM 模块）、Amazon DCV Web UI SDK 中的 `DCVViewer` React 组件、`React` 以及 `Cloudscape Design Global Styles` 软件包。

```
import React from "react";
import dcv from "dcv";
import "@cloudscape-design/global-styles/index.css";
import {DCVViewer} from "./dcv-ui/dcv-ui.js";
```

 以下示例说明了如何在 Amazon DCV 服务器中进行身份验证，并渲染 Amazon DCV Web UI SDK 中的 `DCVViewer` React 组件，但前提是成功进行了身份验证。

```
const LOG_LEVEL = dcv.LogLevel.INFO;
const SERVER_URL = "https://your-dcv-server-url:port/";
const BASE_URL = "/static/js/dcvjs";

let auth;

function App() {
  const [authenticated, setAuthenticated] = React.useState(false);
  const [sessionId, setSessionId] = React.useState('');
  const [authToken, setAuthToken] = React.useState('');
  const [credentials, setCredentials] = React.useState({});

  const onSuccess = (_, result) => {
    var { sessionId, authToken } = { ...result[0] };

    console.log("Authentication successful.");

    setSessionId(sessionId);
    setAuthToken(authToken);
    setAuthenticated(true);
    setCredentials({});
  }

  const onPromptCredentials = (_, credentialsChallenge) => {
    let requestedCredentials = {};

    credentialsChallenge.requiredCredentials.forEach(challenge => requestedCredentials[challenge.name] = "");
    setCredentials(requestedCredentials);
  }

  const authenticate = () => {
    dcv.setLogLevel(LOG_LEVEL);

    auth = dcv.authenticate(
      SERVER_URL,
      {
        promptCredentials: onPromptCredentials,
        error: onError,
        success: onSuccess
      }
    );
  }

  const updateCredentials = (e) => {
    const { name, value } = e.target;
    setCredentials({
      ...credentials,
      [name]: value
    });
  }

  const submitCredentials = (e) => {
    auth.sendCredentials(credentials);
    e.preventDefault();
  }

  React.useEffect(() => {
    if (!authenticated) {
      authenticate();
    }
  }, [authenticated]);

  const handleDisconnect = (reason) => {
    console.log("Disconnected: " + reason.message + " (code: " + reason.code + ")");
    auth.retry();
    setAuthenticated(false);
  }

  return (
    authenticated ?
    <DCVViewer
      dcv={{
        sessionId: sessionId,
        authToken: authToken,
        serverUrl: SERVER_URL,
        baseUrl: BASE_URL,
        onDisconnect: handleDisconnect,
        logLevel: LOG_LEVEL
      }}
      uiConfig={{
        toolbar: {
          visible: true,
          fullscreenButton: true,
          multimonitorButton: true,
        },
      }}
    />
    :
    <div
      style={{
        height: window.innerHeight,
        backgroundColor: "#373737",
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
      }}
    >
      <form>
        <fieldset>
          {Object.keys(credentials).map((cred) => (
            <input
              key={cred}
              name={cred}
              placeholder={cred}
              type={cred === "password" ? "password" : "text"}
              onChange={updateCredentials}
              value={credentials[cred]}
            />
          ))}
        </fieldset>
        <button
          type="submit"
          onClick={submitCredentials}
        >
          Login
        </button>
      </form>
    </div>
  );
}

const onError = (_, error) => {
  console.log("Error during the authentication: " + error.message);
}

export default App;
```

 `promptCredentials`、`error` 和 `success` 函数是在身份验证过程中必须定义的必需回调函数。

 如果 Amazon DCV 服务器提示输入凭证，则 `promptCredentials` 回调函数从 Amazon DCV 服务器接收请求的凭证质询。如果 Amazon DCV 服务器配置为使用系统身份验证，则必须以用户名和密码形式提供凭证。

 如果身份验证失败，则 `error` 回调函数从 Amazon DCV 服务器收到一个错误对象。

 如果身份验证成功，则 `success` 回调函数收到一个对象对数组，其中包括允许用户在 Amazon DCV 服务器上连接到的每个会话的会话 ID（`sessionId`）和授权令牌（`authToken`）。上面的代码示例更新 React 状态，以在成功进行身份验证时渲染 `DCVViewer` 组件。

 要了解该组件接受的属性的更多信息，请参阅 [Amazon DCV Web UI SDK 参考](https://docs.aws.amazon.com/dcv/latest/websdkguide/dcv-viewer.html#DCVViewer)。

 要了解自签名证书的更多信息，请参阅[自签名证书的重定向说明](https://docs.aws.amazon.com/dcv/latest/adminguide/redirection-clarifications-with-self-signed-certs.html)。

## 从 AWS-UI 更新为 Cloudscape Design 系统


 从 SDK 版本 1.3.0 开始，我们将 `DCVViewer` 组件从 AWS-UI 更新为演进版本：[Cloudscape Design](https://cloudscape.design/)。

 Cloudscape 使用与 AWS-UI 不同的视觉主题，但底层代码库保持不变。因此，根据 `DCVViewer` 迁移您的应用程序应该很容易。要进行迁移，请将您安装的 AWS-UI 相关 NPM 软件包替换为关联的 Cloudscape 软件包：


| AWS-UI 软件包名称 | Cloudscape 软件包名称 | 
| --- | --- | 
| @awsui/components-react | @cloudscape-design/components | 
| @awsui/global-styles | @cloudscape-design/global-styles | 
| @awsui/collection-hooks | @cloudscape-design/collection-hooks | 
| @awsui/design-tokens | @cloudscape-design/design-tokens | 

 有关迁移的更多详细信息，请参阅 [AWS-UI GitHub ](https://github.com/aws/awsui-documentation) 文档页面。