Compartilhar via


Habilitar o compartilhamento de arquivos usando a Biblioteca de Interface do Usuário no Chat dos Serviços de Comunicação do Azure com o Armazenamento de Blobs do Azure

Importante

Este recurso dos Serviços de Comunicação do Azure estão atualmente em versão prévia.

Versões prévias das APIs e dos SDKs são fornecidas sem um contrato de nível de serviço. É recomendável que você não as use para cargas de trabalho de produção. Alguns recursos podem não ter suporte ou talvez ter restrição de recursos.

Para saber mais, consulte os Termos de Uso Complementares das Versões Prévias do Microsoft Azure.

Em um Chat dos Serviços de Comunicação do Azure, podemos habilitar o compartilhamento de arquivos entre os usuários de comunicação. Observe que o Serviços de Comunicação do Azure de Chat é diferente do Chat de Interoperabilidade do Teams ("Chat de Interoperabilidade"). Se você quiser habilitar o compartilhamento de arquivos em um Chat de Interoperabilidade, confira Adicionar compartilhamento de arquivos com a Biblioteca de Interface do Usuário no Chat de Interoperabilidade do Teams.

Neste tutorial, estamos configurando a Biblioteca de Interface do Usuário do Chat Composto dos Serviços de Comunicação Azure para habilitar o compartilhamento de arquivos. A Composição de Chat da Biblioteca de Interface do Usuário 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 usando o Armazenamento de Blobs do Azure para habilitar o armazenamento dos arquivos compartilhados por meio do threads de chats.

Importante

Os Serviços de Comunicação do Azure não fornecem um serviço de armazenamento de arquivos. Você precisa utilizar seu próprio serviço de armazenamento de arquivos para compartilhá-los. Para o propósito deste tutorial, estamos usando o Armazenamento de Blobs do Azure.**

Código de download

Acesse o código completo deste tutorial sobre GitHub. Se você quiser usar o compartilhamento de arquivos usando componentes da interface do usuário, faça referência a este exemplo.

Pré-requisitos

Este tutorial pressupõe que você já saiba como configurar e executar uma Composição de Chat. Você pode seguir o tutorial de Composição de Chat para saber como configurar e executar uma Composição de Chat.

Visão geral

A Composição de Chat da Biblioteca de 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 de Interface do Usuário renderiza o arquivo anexado e dá suporte a várias extensões para configurar a aparência do arquivo enviado. Mais especificamente, ele dá suporte aos seguintes recursos:

  1. Botão Anexar arquivo para escolher arquivos por meio do Seletor de Arquivos do sistema operacional
  2. Configurar extensões de arquivo permitidas.
  3. Habilitar/desabilitar vários uploads.
  4. Ícones de arquivo para uma ampla variedade de tipos de arquivo.
  5. Cartões de upload/download de arquivos 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 upload e remover um arquivo carregado antes de ser enviado.
  8. Exiba 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 em que os desenvolvedores precisam implementá-los.

Fluxo típico do compartilhamento de arquivos

Configurar o armazenamento de arquivos usando um blob do Azure

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

Depois de implementado, você pode chamar essa Função do Azure dentro da função handleAttachmentSelection para carregar arquivos para o Armazenamento de Blobs do Azure. Para o restante do tutorial, presumimos que você tenha gerado a função utilizando o tutorial para o Armazenamento de Blobs do Azure vinculado anteriormente.

Proteger seu Contêiner do Armazenamento de Blobs do Azure

Este tutorial pressupõe que o contêiner de armazenamento de blobs 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 carregados no Armazenamento de Blobs do Azure, você pode usar SAS (assinaturas de acesso compartilhado). Uma assinatura de acesso compartilhado (SAS) fornece acesso delegado protegido aos recursos da sua conta de armazenamento. Com uma SAS, você tem controle granular sobre como um cliente pode acessar seus dados.

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

A Biblioteca da IU exige a configuração de um ambiente do React. Avançaremos para isso. Caso você já tenha um aplicativo React, ignore esta seção.

Configurar o aplicativo React

Utilizamos o modelo create-react-app nesse 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 os arquivos dentro da pasta src.

Instalar o pacote

Use o comando npm install 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-reactespecifica o núcleo Serviços de Comunicação do Azure para peerDependencies que você possa usar a API de forma mais consistente das bibliotecas principais em seu aplicativo. 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

Configurar a Composição de Chat para habilitar o compartilhamento de arquivos

Você precisa substituir os valores das duas variáveis comuns exigidas para inicializar o Chat Composto.

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 upload para usar o Armazenamento de Blobs do Azure

Para habilitar o upload do Armazenamento de Blobs do Azure, modificamos o método uploadFileToAzureBlob declarado anteriormente com o código a seguir. Você precisa substituir as informações do Azure Function 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 progess.
      uploadTask.notifyUploadProgressChanged(p.loaded / p.total);
    },
  });

  const storageBaseUrl = "https://<YOUR_STORAGE_ACCOUNT>.blob.core.windows.net";

  return {
    url: `${storageBaseUrl}/${username}/${filename}`,
  };
};

Tratamento de erros

Quando um upload falha, a Composição de Chat da Biblioteca de Interface do Usuário exibe uma mensagem de erro.

Barra de Erro de Upload de Arquivo

Aqui está um exemplo de código que mostra como você pode falhar ao carregar um arquivo 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 de interface do usuário abrirá uma nova guia apontando para a URL que você definiu ao notifyUploadCompleted. Como alternativa, você pode ter uma lógica personalizada para lidar com os downloads de anexo ao actionsForAttachment. Vamos analisar 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 houver problemas durante o download e o usuário precisar ser notificado, podemos apenas throw um erro com uma mensagem na função onClick, então a mensagem será mostrada na barra de erros na parte superior do Chat Composite.

Erro de Download de Arquivo

Limpar os recursos

Se quiser limpar e remover uma assinatura dos Serviços de Comunicação, exclua o recurso ou o grupo de recursos. Excluir o grupo de recursos também exclui todos os recursos associados a ele. Saiba mais sobre como limpar os recursos dos Serviços de Comunicação do Azure e como limpar os recursos do Azure Function.

Próximas etapas

Você também pode querer: