Compartir a través de


Habilitar el uso compartido de archivos mediante la biblioteca de interfaz de usuario en Azure Communication Services Chat con Azure Blob Storage

Importante

Esta característica de Azure Communication Services se encuentra actualmente en versión preliminar.

Las API y los SDK en versión preliminar se proporcionan sin contrato de nivel de servicio. Se recomienda no usarlos para las cargas de trabajo de producción. Es posible que algunas características no sean compatibles o que sus funcionalidades estén limitadas.

Para obtener más información, consulte Términos de uso complementarios para las Versiones preliminares de Microsoft Azure.

En Azure Communication Services Chat, podemos habilitar el uso compartido de archivos entre usuarios de comunicación. Tenga en cuenta que Azure Communication Services Chat es diferente del chat de interoperabilidad de equipos ("chat de interoperabilidad"). Si desea habilitar el uso compartido de archivos en un chat de interoperabilidad, consulte Agregar uso compartido de archivos con la biblioteca de interfaz de usuario en el chat de interoperabilidad de equipos.

En este tutorial, configuraremos la composición de chat de la biblioteca de la interfaz de usuario de Azure Communication Services para habilitar el uso compartido de archivos. La composición de chat de la biblioteca de interfaz de usuario proporciona un conjunto de componentes enriquecidos y controles de interfaz de usuario que se pueden usar para habilitar el uso compartido de archivos. Estamos usando Azure Blob Storage para habilitar el almacenamiento de los archivos que se comparten a través de la conversación de chat.

Importante

Azure Communication Services no proporciona un servicio de almacenamiento de archivos. Tendrá que usar su propio servicio de almacenamiento de archivos para compartir archivos. Para el propósito de este tutorial, usaremos Azure Blob Storage.**

Descarga de código

Acceda al código completo de este tutorial sobre GitHub. Si desea usar el uso compartido de archivos mediante componentes de interfaz de usuario, haga referencia a esta muestra.

Requisitos previos

Este tutorial asume que usted ya sabe cómo configurar y ejecutar una composición de chat. Puede seguir el tutorial de composición de chat para aprender a configurar y ejecutar una composición de chat.

Información general

La composición de chat de biblioteca de interfaz de usuario admite el uso compartido de archivos al permitir que los desarrolladores pasen la dirección URL a un archivo hospedado que se envía a través del servicio de chat de Azure Communication Services. La biblioteca de interfaz de usuario representa el archivo adjunto y admite varias extensiones para configurar la apariencia del archivo enviado. Más concretamente, admite las siguientes características:

  1. Botón Adjuntar archivo para seleccionar archivos a través del selector de archivos del sistema operativo
  2. Configurar las extensiones de archivo permitidas.
  3. Habilitar o deshabilitar varias cargas.
  4. Iconos de archivo para una amplia variedad de tipos de archivo.
  5. Cargar o descargar tarjetas con indicadores de progreso.
  6. Validar dinámicamente cada carga de archivos y mostrar errores en la interfaz de usuario.
  7. Posibilidad de cancelar una carga y quitar un archivo cargado antes de que se envíe.
  8. Ver los archivos cargados en MessageThread y descargrlos. Permite descargas asincrónicas.

Este diagrama programa un flujo típico de un escenario de uso compartido de archivos para cargar y descargar. En la sección marcada como Client Managed se programan los bloques compilados donde los desarrolladores necesitan tenerlos implementados.

Flujo típico de uso compartido de archivos

Configuración del almacenamiento de archivos mediante Azure Blob

Puede seguir el tutorial Carga de un archivo en Azure Blob Storage con una función de Azure para escribir el código back-end necesario para el uso compartido de archivos.

Una vez implementada, puede llamar a esta función de Azure dentro de la función handleAttachmentSelection para cargar archivos en Azure Blob Storage. En el resto del tutorial, se supone que generó la función mediante el tutorial para Azure Blob Storage vinculado anteriormente.

Protección del contenedor de almacenamiento Azure Blob

Este tutorial asume que el contenedor de almacenamiento blob de Azure permite el acceso público a los archivos cargados. No se recomienda que los contenedores de almacenamiento de Azure sean públicos para las aplicaciones de producción reales.

Para descargar los archivos que cargue en el almacenamiento blob de Azure, puede usar firmas de acceso compartido (SAS). Una Firma de acceso compartido (SAS) ofrece acceso delegado seguro a los recursos en la cuenta de almacenamiento. Con una SAS, tiene control granular sobre la forma en que un cliente puede tener acceso a los datos.

En el ejemplo de GitHub descargable se muestra el uso de la firma de acceso compartido para crear direcciones URL de SAS en el contenido de Azure Storage. Además, puede obtener más información sobre SAS.

La biblioteca de interfaz de usuario requiere la configuración de un entorno React. A continuación, se hace eso. Si ya tiene una aplicación React, puede omitir esta sección.

Configuración de la aplicación React

En este inicio rápido se usará la plantilla create-react-app. Para más información, consulte: Introducción a React


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

cd ui-library-quickstart-composites

Al final de este proceso, debería tener una aplicación completa dentro de la carpeta ui-library-quickstart-composites. Para este inicio rápido, estamos modificando archivos dentro de la carpeta src.

Instalar el paquete

Use el comando npm install para instalar la biblioteca de la interfaz de usuario de Azure Communication Services para JavaScript.


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

@azure/communication-reactespecifica los servicios Azure Communication Services principales para que peerDependencies pueda usar la API de forma más coherente desde las bibliotecas principales de la aplicación. También debe instalar esas bibliotecas:


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

Crear aplicación React

Vamos a probar la instalación de la plantilla create-react-app mediante la ejecución de:


npm run start

Configuración de composición de chat para habilitar el uso compartido de archivos

Es necesario reemplazar los valores de variable para ambas variables comunes necesarias para inicializar la composición del 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 el método de carga para usar el almacenamiento Azure Blob

Para habilitar la carga de Azure Blob Storage, modificamos el método uploadFileToAzureBlob que declaramos anteriormente con el siguiente código. Es necesario reemplazar la información de la función Azure para cargar archivos.

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

Control de errores

Cuando falla una carga, la composición de chat de la biblioteca de interfaz de usuario mostrará un mensaje de error.

Barra de error de carga de archivos

A continuación se muestra un ejemplo de código que muestra cómo puede fallar una carga debido a un error de validación de tamaño:

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

Descargas de archivos: uso avanzado

De forma predeterminada, la biblioteca de interfaz de usuario abrirá una nueva pestaña que apunte a la dirección URL que ha establecido al notifyUploadCompleted. Como alternativa, puede tener una lógica personalizada para controlar las descargas de datos adjuntos a través de actionsForAttachment. Echemos un vistazo a un ejemplo.

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

Si hubiera algún problema durante la descarga y necesitamos avisar al usuario, podemos simplemente throw un error con un mensaje en la función onClick y el mensaje se mostrará en la barra de error en la parte superior de la composición de chat.

Error de descarga de archivos

Limpieza de recursos

Si quiere limpiar y quitar una suscripción a Communication Services, puede eliminar el recurso o grupo de recursos. Al eliminar el grupo de recursos, también se elimina cualquier otro recurso que esté asociado a él. Puede encontrar más información sobre la limpieza de los recursos de Azure Communication Services y la limpieza de los recursos de Azure Functions.

Pasos siguientes

Puede que también le interese: