重要
Azure Communication Services のこの機能は、現在プレビュー段階にあります。 プレビュー段階の機能は一般公開されており、新規および既存の Microsoft のすべてのお客様が使用できます。
プレビューの API と SDK は、サービス レベル アグリーメントなしに提供されます。 運用環境のワークロードには使用しないことをお勧めします。 特定の機能がサポートされていないか、機能が制約されている可能性があります。
詳しくは、Microsoft Azure プレビューの追加使用条件に関するページをご覧ください。
Azure Communication Services のチャットでは、通信ユーザー間でファイル共有を有効にすることができます。 Azure Communication Services チャットは、Teams 相互運用性チャットまたは 相互運用チャットとは異なります。 相互運用チャットでファイル共有を有効にする場合は、「 Teams 相互運用性チャットで UI ライブラリを使用してファイル共有を追加する」を参照してください。
この記事では、Azure Communication Services UI ライブラリ チャット コンポジットを構成してファイル共有を有効にする方法について説明します。 UI ライブラリ チャット複合には、ファイル共有を有効にするために使用できる豊富なコンポーネントと UI コントロールのセットが用意されています。 私たちは、チャットスレッドを通じて共有されるファイルを保存できるようにするために、Azure Blob Storage を使用しています。
重要
Azure Communication Services は、ファイル ストレージ サービスを提供していません。 ファイルを共有するには、独自のファイルストレージサービスを使用する必要があります。 このチュートリアルでは、Azure Blob Storage の使用方法について説明します。
コードをダウンロード
このチュートリアルの完全なコードについては、「 UI ライブラリ サンプル - UI チャット複合を使用したファイル共有」を参照してください。 UI コンポーネントを使用してファイル共有を使用する場合は、「 UI ライブラリのサンプル - UI コンポーネントを使用したファイル共有」を参照してください。
[前提条件]
- アクティブなサブスクリプションを持つAzureアカウント。 詳細については、無料のアカウントを作成をご覧ください。
- Visual Studio Code を 対応プラットフォーム のいずれかで使用する。
-
Node.js、アクティブ LTS、およびメンテナンス LTS のバージョン (10.14.1 をお勧めします)。
node --version
コマンドを使用して、バージョンを確認してください。 - アクティブなコミュニケーションサービスのリソースと接続文字列。 Communication Services リソースを作成する。
この記事を使用するには、チャット 複合を設定して実行する方法を知っている必要があります。 Chat Composite を設定して実行する方法の詳細については、 ChatComposite チュートリアルを参照してください。
概要
UIライブラリーのChat Compositeは、Azure Communication Servicesチャットサービスを通じて送信されるホストファイルのURLを開発者が渡すことを可能にすることで、ファイル共有をサポートしています。 UIライブラリは添付ファイルをレンダリングし、送信されたファイルの外観や雰囲気を設定するために複数の拡張機能をサポートしています。 具体的には、次の機能をサポートしています。
- OS ファイル ピッカーを使用してファイルを選択するための [ファイルの添付] ボタン。
- 許可されたファイル拡張子を設定します。
- 複数アップロードの有効化/無効化。
- 様々なファイルタイプに対応したファイルアイコン。
- 進捗インジケーター付きのファイルアップロード/ダウンロードカード。
- 各ファイルのアップロードを動的に検証し、UIにエラーを表示する機能。
- 送信前にアップロードをキャンセルし、アップロードしたファイルを削除する機能。
- アップロードされたファイルをメッセージスレッドで確認し、ダウンロードできます。 非同期ダウンロードを許可します。
次の図は、アップロードとダウンロードの両方のファイル共有シナリオの一般的なフローを示しています。
Client Managed
としてマークされたセクションは、開発者がそれらを実装する必要がある構成要素を示しています。
Azure Blob を利用してファイルストレージを設定する
ファイル共有に必要なバックエンドコードを書くために、チュートリアルAzure Functionを使ってファイルをAzure Blob Storageにアップロードするを参考にすることができます。
実装したら、この Azure 関数を handleAttachmentSelection
関数内で呼び出して、Azure Blob Storage にファイルをアップロードできます。 チュートリアルの残りの部分では、前にリンクされた Azure Blob Storage のチュートリアルを使用して関数を生成したものとします。
Azure Blobストレージコンテナーのセキュリティを確保する
この記事では、Azure Blob Storage コンテナーでアップロードするファイルへのパブリック アクセスを許可することを前提としています。 実際の運用アプリケーションでは、Azure Storage コンテナーをパブリックにすることはお勧めしません。
ファイルをダウンロードするには、Azure BLOB ストレージにアップロードします。 その後、Shared Access Signature (SAS) を使用できます。 共有アクセス署名(SAS)は、ストレージアカウント内のリソースに対し、安全な委任アクセスを提供します。 SASを使用すると、クライアントがデータにアクセスする方法を詳細に制御できます。
ダウンロード可能なGitHubサンプルは、Azureストレージのコンテンツに対してSAS URLを作成するためにSASを使用する方法を示しています。 さらに、SASについてもっと読むことができます。
UIライブラリは、React環境が設定されている必要があります。 次にそれを行います。 もしすでにReactアプリをお持ちの場合は、このセクションをスキップできます。
React アプリのセットアップ
このクイックスタートにはcreate-react-appテンプレートを使用します。 詳細については、Reactを始めるを参照してください。
npx create-react-app ui-library-quickstart-composites --template typescript
cd ui-library-quickstart-composites
このプロセスの最後には、フォルダー ui-library-quickstart-composites
内に完全なアプリケーションがあるはずです。
このクイックスタートでは、src
フォルダー内のファイルを変更しています。
パッケージをインストールする
JavaScript 用のベータ版 Azure Communication Services UI ライブラリをインストールするには、npm install
コマンドを使用します。
npm install @azure/communication-react@1.16.0-beta.1
@azure/communication-react
は、peerDependencies
としてコア Azure Communication Services を指定し、アプリケーションのコアライブラリから API を最も一貫して使用できるようにします。 これらのライブラリもインストールする必要があります。
npm install @azure/communication-calling@1.24.1-beta.2
npm install @azure/communication-chat@1.6.0-beta.1
「Create React App」を作成する
Create React Appのインストールをテストするために、次のコマンドを実行します。
npm run start
チャットコンポジットを設定してファイル共有を有効にする
チャットコンポジットを初期化するために必要な共通の変数の値を置き換える必要があります。
App.tsx
import { initializeFileTypeIcons } from '@fluentui/react-file-type-icons';
import {
ChatComposite,
AttachmentUploadTask,
AttachmentUploadOptions,
AttachmentSelectionHandler,
fromFlatCommunicationIdentifier,
useAzureCommunicationChatAdapter
} from '@azure/communication-react';
import React, { useMemo } from 'react';
initializeFileTypeIcons();
function App(): JSX.Element {
// Common variables
const endpointUrl = 'INSERT_ENDPOINT_URL';
const userId = ' INSERT_USER_ID';
const displayName = 'INSERT_DISPLAY_NAME';
const token = 'INSERT_ACCESS_TOKEN';
const threadId = 'INSERT_THREAD_ID';
// We can't even initialize the Chat and Call adapters without a well-formed token.
const credential = useMemo(() => {
try {
return new AzureCommunicationTokenCredential(token);
} catch {
console.error('Failed to construct token credential');
return undefined;
}
}, [token]);
// Memoize arguments to `useAzureCommunicationChatAdapter` so that
// a new adapter is only created when an argument changes.
const chatAdapterArgs = useMemo(
() => ({
endpoint: endpointUrl,
userId: fromFlatCommunicationIdentifier(userId) as CommunicationUserIdentifier,
displayName,
credential,
threadId
}),
[userId, displayName, credential, threadId]
);
const chatAdapter = useAzureCommunicationChatAdapter(chatAdapterArgs);
if (!!chatAdapter) {
return (
<>
<div style={containerStyle}>
<ChatComposite
adapter={chatAdapter}
options={{
attachmentOptions: {
uploadOptions: uploadOptions,
downloadOptions: downloadOptions,
}
}} />
</div>
</>
);
}
if (credential === undefined) {
return <h3>Failed to construct credential. Provided token is malformed.</h3>;
}
return <h3>Initializing...</h3>;
}
const uploadOptions: AttachmentUploadOptions = {
// default is false
disableMultipleUploads: false,
// define mime types
supportedMediaTypes: ["image/jpg", "image/jpeg"]
handleAttachmentSelection: attachmentSelectionHandler,
}
const attachmentSelectionHandler: AttachmentSelectionHandler = async (uploadTasks) => {
for (const task of uploadTasks) {
try {
const uniqueFileName = `${v4()}-${task.file?.name}`;
const url = await uploadFileToAzureBlob(task);
task.notifyUploadCompleted(uniqueFileName, url);
} catch (error) {
if (error instanceof Error) {
task.notifyUploadFailed(error.message);
}
}
}
}
const uploadFileToAzureBlob = async (uploadTask: AttachmentUploadTask) => {
// You need to handle the file upload here and upload it to Azure Blob Storage.
// This is how you can configure the upload
// Optionally, you can also update the file upload progress.
uploadTask.notifyUploadProgressChanged(0.2);
return {
url: 'https://sample.com/sample.jpg', // Download URL of the file.
};
アップロード方法を構成してAzure Blobストレージを使用するように設定する。
Azure Blob Storageのアップロードを有効にするために、以前に宣言したuploadFileToAzureBlob
メソッドを次のコードで修正します。 ファイルをアップロードするために、Azure Functionsの情報を置き換える必要があります。
App.tsx
const uploadFileToAzureBlob = async (uploadTask: AttachmentUploadTask) => {
const file = uploadTask.file;
if (!file) {
throw new Error("uploadTask.file is undefined");
}
const filename = file.name;
const fileExtension = file.name.split(".").pop();
// Following is an example of calling an Azure Function to handle file upload
// The https://learn.microsoft.com/azure/developer/javascript/how-to/with-web-app/azure-function-file-upload
// tutorial uses 'username' parameter to specify the storage container name.
// the container in the tutorial is private by default. To get default downloads working in
// this sample, you need to change the container's access level to Public via Azure Portal.
const username = "ui-library";
// You can get function url from the Azure Portal:
const azFunctionBaseUri = "<YOUR_AZURE_FUNCTION_URL>";
const uri = `${azFunctionBaseUri}&username=${username}&filename=${filename}`;
const formData = new FormData();
formData.append(file.name, file);
const response = await axios.request({
method: "post",
url: uri,
data: formData,
onUploadProgress: (p) => {
// Optionally, you can update the file upload progress.
uploadTask.notifyUploadProgressChanged(p.loaded / p.total);
},
});
const storageBaseUrl = "https://<YOUR_STORAGE_ACCOUNT>.blob.core.windows.net";
return {
url: `${storageBaseUrl}/${username}/${filename}`,
};
};
エラーハンドリング
アップロードが失敗したとき、UIライブラリーのチャットコンポジットはエラーメッセージを表示します。
アップロードをサイズ検証エラーで失敗させる方法を示すサンプルコードは次のとおりです。
App.tsx
import { AttachmentSelectionHandler } from from '@azure/communication-react';
const attachmentSelectionHandler: AttachmentSelectionHandler = async (uploadTasks) => {
for (const task of uploadTasks) {
if (task.file && task.file.size > 99 * 1024 * 1024) {
// Notify ChatComposite about upload failure.
// Allows you to provide a custom error message.
task.notifyUploadFailed('File too big. Select a file under 99 MB.');
}
}
}
export const attachmentUploadOptions: AttachmentUploadOptions = {
handleAttachmentSelection: attachmentSelectionHandler
};
ファイルのダウンロード - 高度な使用法
既定では、UI ライブラリは、 notifyUploadCompleted
したときに設定した URL を指す新しいタブを開きます。 または、カスタム ロジックを使用して、 actionsForAttachment
経由で添付ファイルのダウンロードを処理することもできます。 例を見てみましょう。
App.tsx
import { AttachmentDownloadOptions } from "communication-react";
const downloadOptions: AttachmentDownloadOptions = {
actionsForAttachment: handler
}
const handler = async (attachment: AttachmentMetadata, message?: ChatMessage) => {
// here we are returning a static action for all attachments and all messages
// alternately, you can provide custom menu actions based on properties in `attachment` or `message`
return [defaultAttachmentMenuAction];
};
const customHandler = = async (attachment: AttachmentMetadata, message?: ChatMessage) => {
if (attachment.extension === "pdf") {
return [
{
title: "Custom button",
icon: (<i className="custom-icon"></i>),
onClick: () => {
return new Promise((resolve, reject) => {
// custom logic here
window.alert("custom button clicked");
resolve();
// or to reject("xxxxx") with a custom message
})
}
},
defaultAttachmentMenuAction
];
} else if (message?.senderId === "user1") {
return [
{
title: "Custom button 2",
icon: (<i className="custom-icon-2"></i>),
onClick: () => {
return new Promise((resolve, reject) => {
window.alert("custom button 2 clicked");
resolve();
})
}
},
// you can also override the default action partially
{
...defaultAttachmentMenuAction,
onClick: () => {
return new Promise((resolve, reject) => {
window.alert("default button clicked");
resolve();
})
}
}
];
}
}
ダウンロード中に問題が発生し、ユーザーに通知する必要がある場合は、throw
関数のメッセージでエラーをonClick
できます。 その後、メッセージがチャット複合の上のエラー バーに表示されます。
資源を整理する
通信サービスのサブスクリプションを整理して削除したい場合は、リソースまたはリソースグループを削除できます。 リソースグループを削除すると、それに関連付けられた他のリソースも削除されます。 Azure Communication Services リソースのクリーンアップやAzure Functions リソースのクリーンアップについて詳しく知ることができます。