Partilhar via


Habilitar o compartilhamento de arquivos usando a Biblioteca da Interface do Usuário nos Serviços de Comunicação do Azure Bate-papo com o armazenamento de Blob do Azure

Importante

Esta funcionalidade dos Serviços de Comunicação do Azure está atualmente em pré-visualização.

As APIs e SDKs de visualização são fornecidos sem um contrato de nível de serviço. Recomendamos que você não os use para cargas de trabalho de produção. Alguns recursos podem não ser suportados ou podem ter recursos restritos.

Para obter mais informações, consulte Termos de Utilização Suplementares para Pré-visualizações do Microsoft Azure.

Em um Chat dos Serviços de Comunicação do Azure, podemos habilitar o compartilhamento de arquivos entre usuários de comunicação. Observe que o Chat dos Serviços de Comunicação do Azure é diferente do Chat de Interoperabilidade do Teams ("Chat de Interoperabilidade"). Se você quiser habilitar o compartilhamento de arquivos em um bate-papo de interoperabilidade, consulte Adicionar compartilhamento de arquivos com a biblioteca da interface do usuário no Teams Interoperability Chat.

Neste tutorial, estamos configurando o Composto de Chat da Biblioteca da Interface do Usuário dos Serviços de Comunicação do Azure para habilitar o compartilhamento de arquivos. O UI Library Chat Composite fornece um conjunto de componentes avançados e controles de interface do usuário que podem ser usados para habilitar o compartilhamento de arquivos. Estamos a utilizar o Armazenamento de Blobs do Azure para ativar o armazenamento dos ficheiros que são partilhados através do thread de chat.

Importante

Os Serviços de Comunicação do Azure não fornecem um serviço de armazenamento de ficheiros. Você precisa usar seu próprio serviço de armazenamento de arquivos para compartilhar arquivos. Para este tutorial, estamos usando o Armazenamento de Blobs do Azure.**

Transferir código

Acesse o código completo deste tutorial no GitHub. Se você quiser usar o compartilhamento de arquivos usando componentes da interface do usuário, consulte este exemplo.

Pré-requisitos

Este tutorial pressupõe que você já saiba como configurar e executar um Chat Composite. Você pode seguir o tutorial Chat Composite para aprender a configurar e executar um Chat Composite.

Descrição geral

O Composto de Chat da Biblioteca da Interface do Usuário dá suporte ao compartilhamento de arquivos permitindo que os desenvolvedores passem a URL para um arquivo hospedado que é enviado por meio do serviço de chat dos Serviços de Comunicação do Azure. A biblioteca da interface do usuário processa o arquivo anexado e suporta várias extensões para configurar a aparência do arquivo enviado. Mais especificamente, ele suporta os seguintes recursos:

  1. Botão Anexar ficheiro para selecionar ficheiros através do Selecionador de Ficheiros do SO
  2. Configure extensões de arquivo permitidas.
  3. Ativar/desativar vários carregamentos.
  4. Ícones de arquivo para uma grande variedade de tipos de arquivo.
  5. Cartões de upload/download de ficheiros com indicadores de progresso.
  6. Capacidade de validar dinamicamente cada upload de arquivo e exibir erros na interface do usuário.
  7. Capacidade de cancelar um carregamento e remover um ficheiro carregado antes de ser enviado.
  8. Veja os arquivos carregados no MessageThread, baixe-os. Permite downloads assíncronos.

O diagrama mostra um fluxo típico de um cenário de compartilhamento de arquivos para upload e download. A seção marcada como Client Managed mostra os blocos de construção onde os desenvolvedores precisam implementá-los.

Fluxo típico de compartilhamento de arquivos

Configurar o armazenamento de arquivos usando o Blob do Azure

Você pode seguir o tutorial Carregar arquivo no Armazenamento de Blobs do Azure com uma Função do Azure para escrever o código de back-end necessário para o compartilhamento de arquivos.

Uma vez implementada, você pode chamar essa Função do Azure dentro da handleAttachmentSelection função para carregar arquivos no Armazenamento de Blobs do Azure. Para o restante do tutorial, assumimos que você gerou a função usando o tutorial para o Armazenamento de Blobs do Azure vinculado anteriormente.

Protegendo seu contêiner de armazenamento de Blob do Azure

Este tutorial pressupõe que seu contêiner de armazenamento de blob do Azure permita acesso público aos arquivos carregados. Tornar seus contêineres de armazenamento do Azure públicos não é recomendado para aplicativos de produção do mundo real.

Para baixar os arquivos, você carrega no armazenamento de blob do Azure, pode usar assinaturas de acesso compartilhado (SAS). Uma assinatura de acesso compartilhado (SAS) fornece acesso delegado seguro aos recursos em sua conta de armazenamento. Com uma SAS, você tem controle granular sobre como um cliente pode acessar seus dados.

O exemplo do GitHub baixável mostra o uso do SAS para criar URLs SAS para o conteúdo do Armazenamento do Azure. Além disso, você pode ler mais sobre SAS.

A biblioteca da interface do usuário requer um ambiente React para ser configurado. Em seguida, fazemos isso. Se já tiver uma aplicação React, pode ignorar esta secção.

Configurar o aplicativo react

Usamos o modelo create-react-app para este início rápido. Para obter mais informações, consulte: Introdução ao React


npx create-react-app ui-library-quickstart-composites --template typescript

cd ui-library-quickstart-composites

No final deste processo, você deve ter um aplicativo completo dentro da pasta ui-library-quickstart-composites. Para este início rápido, estamos modificando arquivos dentro da src pasta.

Instalar o pacote

Use o npm install comando para instalar a Biblioteca de Interface do Usuário dos Serviços de Comunicação do Azure beta para JavaScript.


npm install @azure/communication-react@1.16.0-beta.1

@azure/communication-react especifica os Serviços de Comunicação do Azure principais para peerDependencies que você possa usar a API das bibliotecas principais em seu aplicativo de forma mais consistente. Você também precisa instalar essas bibliotecas:


npm install @azure/communication-calling@1.24.1-beta.2
npm install @azure/communication-chat@1.6.0-beta.1

Criar aplicativo React

Vamos testar a instalação do Create React App executando:


npm run start

Configurando o Chat Composite para habilitar o compartilhamento de arquivos

Você precisa substituir os valores das variáveis para ambas as variáveis comuns necessárias para inicializar o composto de chat.

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.
  };

Configurar o método de carregamento para usar o armazenamento de Blob do Azure

Para habilitar o carregamento do Armazenamento de Blobs do Azure, modificamos o uploadFileToAzureBlob método declarado anteriormente com o código a seguir. Você precisa substituir as informações do Azure Function para carregar arquivos.

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}`,
  };
};

Processamento de erros

Quando um carregamento falha, o UI Library Chat Composite exibe uma mensagem de erro.

Barra de erro de carregamento de arquivo

Aqui está um código de exemplo mostrando como você pode falhar em um carregamento devido a um erro de validação de tamanho:

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
};

Downloads de arquivos - uso avançado

Por padrão, a biblioteca da interface do usuário abrirá uma nova guia apontando para a URL que você definiu quando .notifyUploadCompleted Como alternativa, você pode ter uma lógica personalizada para lidar com downloads de anexos via actionsForAttachment. Vejamos um exemplo.

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();
          })
        }
      }
    ];
  }
}

Se houve algum problema durante o download e o usuário precisa ser notificado, podemos apenas throw um erro com uma mensagem na onClick função, então a mensagem seria mostrada na barra de erro no topo do Chat Composite.

Erro de download de arquivo

Clean up resources (Limpar recursos)

Se quiser limpar e remover uma assinatura dos Serviços de Comunicação, você pode excluir o recurso ou grupo de recursos. A exclusão do grupo de recursos também exclui quaisquer outros recursos associados a ele. Você pode saber mais sobre como limpar os recursos dos Serviços de Comunicação do Azure e limpar os Recursos da Função do Azure.

Próximos passos

Você também pode querer: