Partilhar via


Adicionar partilha de ficheiros no chat usando a Biblioteca de Interface com o Utilizador e o armazenamento de Blobs do Azure

Important

Esta funcionalidade dos Serviços de Comunicação do Azure está atualmente em pré-visualização. Os recursos na visualização estão disponíveis publicamente e podem ser usados por todos os clientes novos e existentes da Microsoft.

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 capacidades podem ser restringidas.

Para obter mais informações, veja Termos Suplementares de Utilização 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. O Chat dos Serviços de Comunicação do Azure é diferente do Chat de Interoperabilidade do Teams, ou Interop Chat. 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.

Este artigo descreve como configurar 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 podemos usar 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.

Important

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. Este tutorial descreve como usar o Armazenamento de Blob do Azure.

Transferir código

Acesse o código completo para este tutorial em UI Library Sample - File Sharing using UI Chat Composite. Se você quiser usar o compartilhamento de arquivos usando componentes da interface do usuário, consulte Exemplo de biblioteca da interface do usuário - Compartilhamento de arquivos usando componentes da interface do usuário.

Prerequisites

Para usar este artigo, você precisa saber como configurar e executar um Chat Composite. Para obter mais informações sobre como configurar e executar um Chat Composite, consulte o tutorial ChatComposto.

Overview

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 para anexar ficheiro para selecionar ficheiros através do Selecionador de Ficheiros do Sistema Operativo.
  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 upload e remover um arquivo carregado antes de enviar.
  8. Veja os arquivos carregados no MessageThread, baixe-os. Permite downloads assíncronos.

O diagrama a seguir 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 Blob do Azure vinculado anteriormente.

Protegendo seu contêiner de armazenamento de Blob do Azure

Este artigo 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, envie-os para o armazenamento de blob do Azure. Em seguida, você 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 disponível para download mostra o uso do SAS para criar URLs SAS para 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 mais recente para JavaScript.


npm install @azure/communication-react@1.28.0-beta.2

@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.36.1-beta.1
npm install @azure/communication-chat@1.6.0-beta.7

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

function App(): JSX.Element {
  initializeFileTypeIcons();

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

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

Transferências de arquivos - uso avançado

Por padrão, a biblioteca da interface do usuário abre uma nova guia apontando para a URL definida quando você notifyUploadCompleted. Como alternativa, você pode usar 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) => {
  const extension = attachment.name.split(".").pop() || "";
   if (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, você pode throw um erro com uma mensagem na onClick função. Em seguida, a mensagem é exibida na barra de erro na parte superior do Chat Composite.

Erro de download de arquivo

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