Envío de datos adjuntos multimedia con Bot Framework SDK

SE APLICA A: SDK v4

Un intercambio de mensajes entre el usuario y el bot puede contener datos adjuntos con elementos multimedia, como imágenes, vídeo, audio y archivos. Bot Framework SDK es compatible con la tarea de enviar mensajes enriquecidos al usuario. Para determinar el tipo de mensajes enriquecidos que admite un canal (Facebook, Slack, etc.), consulte la documentación del canal para más información sobre las limitaciones.

Nota:

Los SDK de JavaScript, C# y Python de Bot Framework seguirán siendo compatibles, pero el SDK de Java se va a retirar con la compatibilidad final a largo plazo que finaliza en noviembre de 2023.

Los bots existentes creados con el SDK de Java seguirán funcionando.

Para la nueva compilación de bots, considere la posibilidad de usar Microsoft Copilot Studio y lea sobre cómo elegir la solución de copilot adecuada.

Para obtener más información, consulta El futuro de la creación de bots.

Requisitos previos

Envío de datos adjuntos

Para enviar el contenido de usuario como una imagen o un vídeo, puede agregar datos adjuntos o una lista de datos adjuntos a un mensaje.

Consulte Diseñar la experiencia del usuario para obtener una lista de las tarjetas disponibles.

Consulte también ¿Cuál es el límite de tamaño de un archivo transferido mediante canales? en las preguntas más frecuentes.

Todo el código fuente que se muestra en esta sección se basa en el ejemplo Handling attachments.

La propiedad Attachments del objeto Activity contiene una matriz de objetos Attachment que representan los datos adjuntos con elementos multimedia y las tarjetas enriquecidas adjuntas al mensaje. Para agregar datos adjuntos con elementos multimedia a un mensaje, cree un objeto Attachment para la actividad reply y establezca las propiedades ContentType, ContentUrl y Name.

Para crear el mensaje de respuesta, defina el texto y, a continuación, configure los datos adjuntos. La asignación de los datos adjuntos a la respuesta es la misma para cada tipo de archivo adjunto, aunque los distintos datos adjuntos se configuran y definen de manera diferente, tal como se muestra en los siguientes fragmentos de código. El código siguiente configura la respuesta para los datos adjuntos insertados:

Bots/AttachmentsBot.cs

{
    reply = MessageFactory.Text("This is an inline attachment.");

A continuación, nos centramos en los tipos de datos adjuntos. Primero, datos adjuntos insertados:

Bots/AttachmentsBot.cs

{
    var imagePath = Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png");
    var imageData = Convert.ToBase64String(File.ReadAllBytes(imagePath));

    return new Attachment
    {
        Name = @"Resources\architecture-resize.png",
        ContentType = "image/png",
        ContentUrl = $"data:image/png;base64,{imageData}",
    };
}

Seguidamente, datos adjuntos cargados:

Bots/AttachmentsBot.cs

{
    if (string.IsNullOrWhiteSpace(serviceUrl))
    {
        throw new ArgumentNullException(nameof(serviceUrl));
    }

    if (string.IsNullOrWhiteSpace(conversationId))
    {
        throw new ArgumentNullException(nameof(conversationId));
    }

    var imagePath = Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png");

    var connector = turnContext.TurnState.Get<IConnectorClient>() as ConnectorClient;
    var attachments = new Attachments(connector);
    var response = await attachments.Client.Conversations.UploadAttachmentAsync(
        conversationId,
        new AttachmentData
        {
            Name = @"Resources\architecture-resize.png",
            OriginalBase64 = File.ReadAllBytes(imagePath),
            Type = "image/png",
        },
        cancellationToken);

    var attachmentUri = attachments.GetAttachmentUri(response.Id);

    return new Attachment
    {
        Name = @"Resources\architecture-resize.png",
        ContentType = "image/png",
        ContentUrl = attachmentUri,
    };
}

Por último, un archivo adjunto de Internet:

Bots/AttachmentsBot.cs

    {
        // ContentUrl must be HTTPS.
        return new Attachment
        {
            Name = @"Resources\architecture-resize.png",
            ContentType = "image/png",
            ContentUrl = "https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png",
        };
    }
}

Si los datos adjuntos son una imagen, un audio o un vídeo, el servicio del conector comunicará los datos adjuntos al canal de una manera que permita que el canal presente esos datos adjuntos dentro de la conversación. Si los datos adjuntos son un archivo, la dirección URL del archivo se presentará como un hipervínculo dentro de la conversación.

Envío de una tarjeta de imagen prominente

Además de los datos adjuntos de imagen o vídeo sencillos, puede adjuntar una tarjeta de imagen prominente que le permite combinar las imágenes y los botones en un objeto y los envían al usuario. Markdown es compatible con la mayoría de los campos de texto, pero la compatibilidad puede variar según el canal.

Para redactar un mensaje con un botón y una tarjeta de imagen prominente, puede adjuntar un objeto HeroCard a un mensaje.

El siguiente código fuente procede del ejemplo Control de datos adjuntos.

Bots/AttachmentsBot.cs


      private static async Task DisplayOptionsAsync(ITurnContext turnContext, CancellationToken cancellationToken)
      {
          // Create a HeroCard with options for the user to interact with the bot.
          var card = new HeroCard
          {
              Text = "You can upload an image or select one of the following choices",
              Buttons = new List<CardAction>
              {
                  // Note that some channels require different values to be used in order to get buttons to display text.
                  // In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
                  // need to provide a value for other parameters like 'text' or 'displayText'.
                  new CardAction(ActionTypes.ImBack, title: "1. Inline Attachment", value: "1"),
                  new CardAction(ActionTypes.ImBack, title: "2. Internet Attachment", value: "2"),
                  new CardAction(ActionTypes.ImBack, title: "3. Uploaded Attachment", value: "3"),
              },
          };

          var reply = MessageFactory.Attachment(card.ToAttachment());
          await turnContext.SendActivityAsync(reply, cancellationToken);

Procesamiento de eventos dentro de tarjetas enriquecidas

Para procesar eventos dentro de tarjetas enriquecidas, use los objetos de acción de tarjeta para especificar qué debe ocurrir cuando el usuario selecciona un botón o pulsa una sección de la tarjeta. Cada acción de la tarjeta tiene una propiedad de tipo y valor.

Para que el funcionamiento sea correcto, asigne un tipo de acción a cada elemento en el que se puede hacer clic en la tarjeta de elemento principal. Esta tabla enumera y describe los tipos de acciones disponibles y lo que debería estar en la propiedad de valor asociada.

La acción de la tarjeta messageBack tiene un significado más generalizado que las demás acciones de tarjeta. Consulte la sección Acción de tarjeta del Esquema de actividad para obtener más información sobre el messageBack y otros tipos de acción de tarjeta.

Tipo Descripción Valor
call Inicia una llamada de teléfono. Destino de una llamada telefónica con este formato: tel:123123123123.
DownloadFile Descarga un archivo. La dirección URL del archivo que se va a descargar.
imBack Envía un mensaje al bot y publica una respuesta visible en el chat. Texto del mensaje para enviar.
messageBack Representa una respuesta de texto que se debe enviar a través del sistema de chat. Valor de programación opcional que se va a incluir en los mensajes generados.
openUrl Se abre una dirección URL en el explorador integrado. Dirección URL que se va a abrir.
playAudio Reproduce audio. La dirección URL del audio que se va a reproducir.
playVideo Reproduce un vídeo. La dirección URL del vídeo que se va a reproducir.
postBack Envía un mensaje al bot y puede no publicar una respuesta visible en el chat. Texto del mensaje para enviar.
showImage Muestra una imagen. La dirección URL de la imagen que se va a mostrar.
signin Inicia un proceso de inicio de sesión de OAuth. La dirección URL del flujo de OAuth que se va a iniciar.

Tarjeta de imagen prominente a través de varios tipos de evento

El código siguiente muestra ejemplos que usan varios eventos de tarjeta enriquecida.

Para obtener ejemplos de todas las tarjetas disponibles, consulte el ejemplo de uso de tarjetas.

Cards.cs

public static HeroCard GetHeroCard()
{
    var heroCard = new HeroCard
    {
        Title = "BotFramework Hero Card",
        Subtitle = "Microsoft Bot Framework",
        Text = "Build and connect intelligent bots to interact with your users naturally wherever they are," +
               " from text/sms to Skype, Slack, Office 365 mail and other popular services.",
        Images = new List<CardImage> { new CardImage("https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg") },
        Buttons = new List<CardAction> { new CardAction(ActionTypes.OpenUrl, "Get Started", value: "https://docs.microsoft.com/bot-framework") },
    };

    return heroCard;
}

Cards.cs

public static SigninCard GetSigninCard()
{
    var signinCard = new SigninCard
    {
        Text = "BotFramework Sign-in Card",
        Buttons = new List<CardAction> { new CardAction(ActionTypes.Signin, "Sign-in", value: "https://login.microsoftonline.com/") },
    };

    return signinCard;
}

Envío de una tarjeta adaptable

Aunque puede usar el generador de mensajes para crear un mensaje que contenga datos adjuntos (de cualquier tipo), una tarjeta adaptable es un tipo específico de datos adjuntos. No todos los canales admiten Tarjetas adaptables, y algunos canales pueden admitir solo parcialmente Tarjetas adaptables. Por ejemplo, si envía una tarjeta adaptable en Facebook, los botones no funcionarán, pero los textos y las imágenes funcionan bien. La fábrica de mensajes es una clase auxiliar del SDK de Bot Framework que se utiliza para automatizar los pasos de creación por usted.

Las tarjetas adaptables son un formato abierto de intercambio de tarjetas que permite a los desarrolladores intercambiar contenido de la interfaz de usuario de una manera común y coherente. Sin embargo, no todos los canales admiten las tarjetas adaptables.

El diseñador de tarjetas adaptables ofrece una experiencia enriquecida e interactiva en tiempo de diseño para crear tarjetas adaptables.

Nota:

Debe probar esta característica con los canales que el bot usará para determinar si esos canales admiten las tarjetas adaptables.

Para usar las tarjetas adaptables, no olvide agregar el paquete de NuGet AdaptiveCards.

El siguiente código fuente procede del ejemplo Uso de tarjetas.

Cards.cs

En este ejemplo se lee el JSON de tarjeta adaptable de un archivo y se agrega como datos adjuntos.

public static Attachment CreateAdaptiveCardAttachment()
{
    // combine path for cross platform support
    var paths = new[] { ".", "Resources", "adaptiveCard.json" };
    var adaptiveCardJson = File.ReadAllText(Path.Combine(paths));

    var adaptiveCardAttachment = new Attachment()
    {
        ContentType = "application/vnd.microsoft.card.adaptive",
        Content = JsonConvert.DeserializeObject(adaptiveCardJson),
    };

    return adaptiveCardAttachment;
}

Los mensajes también pueden incluir varios datos adjuntos en un diseño de carrusel, que coloca los datos adjuntos en paralelo y permite que el usuario se desplace por ellos.

El siguiente código fuente procede del ejemplo Uso de tarjetas.

Dialogs/MainDialog.cs

En primer lugar, se crea la respuesta y se definen los datos adjuntos como una lista.

// Cards are sent as Attachments in the Bot Framework.
// So we need to create a list of attachments for the reply activity.
var attachments = new List<Attachment>();

// Reply to the activity we received with an activity.
var reply = MessageFactory.Attachment(attachments);

A continuación, agregue los datos adjuntos y establezca el tipo de diseño en carrusel. Aquí se agregan uno cada vez, pero, si quiere, puede manipular la lista para agregar las tarjetas.

// Display a carousel of all the rich card types.
reply.AttachmentLayout = AttachmentLayoutTypes.Carousel;
reply.Attachments.Add(Cards.CreateAdaptiveCardAttachment());
reply.Attachments.Add(Cards.GetAnimationCard().ToAttachment());
reply.Attachments.Add(Cards.GetAudioCard().ToAttachment());
reply.Attachments.Add(Cards.GetHeroCard().ToAttachment());
reply.Attachments.Add(Cards.GetOAuthCard().ToAttachment());
reply.Attachments.Add(Cards.GetReceiptCard().ToAttachment());
reply.Attachments.Add(Cards.GetSigninCard().ToAttachment());
reply.Attachments.Add(Cards.GetThumbnailCard().ToAttachment());
reply.Attachments.Add(Cards.GetVideoCard().ToAttachment());

Una vez que se han agregado los datos adjuntos, puede enviar la respuesta como cualquier otra.

// Send the card(s) to the user as an attachment to the activity
await stepContext.Context.SendActivityAsync(reply, cancellationToken);

Ejemplo de código para procesar la entrada de tarjeta adaptable

El siguiente ejemplo muestra una forma de usar las entradas de tarjeta adaptable dentro de una clase de cuadro de diálogo de bot. Extiende el ejemplo .e las tarjetas de elemento principal actual mediante la validación de la entrada recibida en el campo de texto desde el cliente que responde. Primero tiene que añadir la funcionalidad de entrada de texto y botón a la tarjeta adaptable existente añadiendo el siguiente código justo antes de la llave final de adaptiveCard.json, situada en la carpeta de recursos:

"actions": [
  {
    "type": "Action.ShowCard",
    "title": "Text",
    "card": {
      "type": "AdaptiveCard",
      "body": [
        {
          "type": "Input.Text",
          "id": "text",
          "isMultiline": true,
          "placeholder": "Enter your comment"
        }
      ],
      "actions": [
        {
          "type": "Action.Submit",
          "title": "OK"
        }
      ]
    }
  }
]

El identificador del campo de entrada de texto se establece en "text". Cuando el usuario selecciona Aceptar, el mensaje que genera la tarjeta adaptable tendrá una propiedad de valor que tiene una propiedad denominada text que contiene la información especificada por el usuario en el campo de entrada de texto de la tarjeta.

El validador usa Newtonsoft.json para convertirlo primero en un elemento JObject y, a continuación, crea una cadena de texto recortado para la comparación. Por tanto, agregue:

using System;
using System.Linq;
using Newtonsoft.Json.Linq;

a MainDialog.cs e instale el paquete de nuget estable más reciente de Newtonsoft.Json. En el código del validador, agregamos el flujo de lógica a los comentarios del código. Este método ChoiceValidator se coloca en el ejemplo Uso de tarjetas justo después de la llave de cierre pública para la declaración de MainDialog:

private async Task ChoiceValidator(
    PromptValidatorContext promptContext,
    CancellationToken cancellationToken)
{
    // Retrieves Adaptive Card comment text as JObject.
    // looks for JObject field "text" and converts that input into a trimmed text string.
    var jobject = promptContext.Context.Activity.Value as JObject;
    var jtoken = jobject?["text"];
    var text = jtoken?.Value().Trim();

    // Logic: 1. if succeeded = true, just return promptContext
    //        2. if false, see if JObject contained Adaptive Card input.
    //               No = (bad input) return promptContext
    //               Yes = update Value field with JObject text string, return "true".
    if (!promptContext.Recognized.Succeeded && text != null)
    {
        var choice = promptContext.Options.Choices.FirstOrDefault(
        c => c.Value.Equals(text, StringComparison.InvariantCultureIgnoreCase));
        if (choice != null)
        {
            promptContext.Recognized.Value = new FoundChoice
            {
                Value = choice.Value,
            };
            return true;
        }
    }
    return promptContext.Recognized.Succeeded;
}

Arriba en la declaración MainDialog, cambie:

// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));

a:

// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt), ChoiceValidator));

Esto invocará el validador para buscar entrada de tarjeta adaptable cada vez que se crea un nuevo elemento ChoicePrompt.

Pruebe el bot Uso de tarjetas

  1. Ejecute localmente la muestra Uso de tarjetas y abra el bot en el Bot Framework Emulator.
  2. Siga las indicaciones del bot para mostrar un tipo de tarjeta, como una tarjeta adaptable.

Pasos siguientes