Incorporación de elementos multimedia a los mensajesAdd media to messages

se aplica a: SDK V4APPLIES TO: 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.Messages exchanged between user and bot can contain media attachments, such as images, video, audio, and files. Bot Framework SDK es compatible con la tarea de enviar mensajes enriquecidos al usuario.The Bot Framework SDK supports the task of sending rich messages to the user. 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.To determine the type of rich messages a channel (Facebook, Slack, etc.) supports, consult the channel's documentation for information about limitations.

PrerrequisitosPrerequisites

Envío de datos adjuntosSend attachments

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.To send the user content like an image or a video, you can add an attachment or list of attachments to a message.

Consulte diseño de la experiencia del usuario para obtener ejemplos de tarjetas disponibles.See Design the user experience for examples of available cards.

Vea también ¿cuál es el límite de tamaño de un archivo transferido mediante canales? en las preguntas más frecuentes.See also What is the size limit of a file transferred using channels? in the FAQ.

Todo el código fuente que se muestra en esta sección se basa en el ejemplo de control de datos adjuntos .All of the source code shown in this section is based on the Handling attachments sample.

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.The Attachments property of the Activity object contains an array of Attachment objects that represent the media attachments and rich cards attached to the message. 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.To add a media attachment to a message, create an Attachment object for the reply activity and set the ContentType, ContentUrl, and Name properties.

Para crear el mensaje de respuesta, defina el texto y, a continuación, configure los datos adjuntos.To create the reply message, define the text and then set up the attachments. 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.Assigning the attachments to the reply is the same for each attachment type, however the various attachments are set up and defined differently, as seen in the following snippets. El código siguiente configura la respuesta para los datos adjuntos insertados:The code below is setting up the reply for an inline attachment:

Bots/AttachmentsBot.csBots/AttachmentsBot.cs

reply = MessageFactory.Text("This is an inline attachment.");
reply.Attachments = new List<Attachment>() { GetInlineAttachment() };

A continuación, nos centramos en los tipos de datos adjuntos.Next, we look at the types of attachments. Primero, datos adjuntos insertados:First is an inline attachment:

Bots/AttachmentsBot.csBots/AttachmentsBot.cs

private static Attachment GetInlineAttachment()
{
    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:Then, an uploaded attachment:

Bots/AttachmentsBot.csBots/AttachmentsBot.cs

private static async Task<Attachment> GetUploadedAttachmentAsync(ITurnContext turnContext, string serviceUrl, string conversationId, CancellationToken cancellationToken)
{
    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:Lastly, an internet attachment:

Bots/AttachmentsBot.csBots/AttachmentsBot.cs

private static Attachment GetInternetAttachment()
{
    // 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.If an attachment is an image, audio, or video, the Connector service will communicate attachment data to the channel in a way that enables the channel to render that attachment within the conversation. Si los datos adjuntos son un archivo, la dirección URL del archivo se presentará como un hipervínculo dentro de la conversación.If the attachment is a file, the file URL will be rendered as a hyperlink within the conversation.

Envío de una tarjeta de imagen prominenteSend a hero card

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.Besides simple image or video attachments, you can attach a hero card, which allows you to combine images and buttons in one object, and send them to the user. Markdown es compatible con la mayoría de los campos de texto, pero la compatibilidad puede variar según el canal.Markdown is supported for most text fields, but support may vary by channel.

Para redactar un mensaje con una tarjeta y un botón de Heroes, puede adjuntar un HeroCard objeto a un mensaje.To compose a message with a hero card and button, you can attach a HeroCard object to a message.

El código fuente que se muestra aquí se basa en el ejemplo de control de datos adjuntos .The source code shown here is based on the Handling attachments sample.

Bots/AttachmentsBot.csBots/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 enriquecidasProcess events within rich cards

Para procesar eventos dentro de tarjetas enriquecidas, utilice 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.To process events within rich cards, use card action objects to specify what should happen when the user selects a button or taps a section of the card. Cada acción de tarjeta tiene una propiedad de tipo y valor .Each card action has a type and value property.

Para que funcione correctamente, asigne un tipo de acción a cada elemento en el que se pueda hacer clic en una tarjeta Hero.To function correctly, assign an action type to each clickable item on a hero card. Esta tabla enumera y describe los tipos de acciones disponibles y lo que debería estar en la propiedad de valor asociada.This table lists and describes the available action types and what should be in the associated value property. La messageBack acción de tarjeta tiene un significado más generalizado que las demás acciones de tarjeta.The messageBack card action has a more generalized meaning than the other card actions. Vea la sección acción de tarjeta del esquema de actividad para obtener más información acerca de messageBack y otros tipos de acciones de tarjeta.See the Card action section of the Activity schema for more information about the messageBack and other card action types.

TipoType DescripciónDescription ValorValue
llamadacall Inicia una llamada de teléfono.Initiates a phone call. Destino de una llamada telefónica con este formato: tel:123123123123.Destination for the phone call in this format: tel:123123123123.
DownloadFiledownloadFile Descarga un archivo.Downloads a file. La dirección URL del archivo que se va a descargar.The URL of the file to download.
imBackimBack Envía un mensaje al bot y publica una respuesta visible en el chat.Sends a message to the bot, and posts a visible response in the chat. Texto del mensaje para enviar.Text of the message to send.
messageBackmessageBack Representa una respuesta de texto que se va a enviar a través del sistema de chat.Represents a text response to be sent via the chat system. Valor de programación opcional que se va a incluir en los mensajes generados.An optional programmatic value to include in generated messages.
openUrlopenUrl Se abre una dirección URL en el explorador integrado.Opens a URL in the built-in browser. Dirección URL que se va a abrir.The URL to open.
playAudioplayAudio Reproduce audio.Plays audio. La dirección URL del audio que se va a reproducir.The URL of the audio to play.
playVideoplayVideo Reproduce un vídeo.Plays a video. La dirección URL del vídeo que se va a reproducir.The URL of video to play.
postBackpostBack Envía un mensaje al bot y puede no publicar una respuesta visible en el chat.Sends a message to the bot, and may not post a visible response in the chat. Texto del mensaje para enviar.Text of the message to send.
showImageshowImage Muestra una imagen.Displays an image. La dirección URL de la imagen que se va a mostrar.The URL of the image to display.
signinsignin Inicia un proceso de inicio de sesión de OAuth.Initiates an OAuth sign-in process. La dirección URL del flujo de OAuth que se va a iniciar.The URL of the OAuth flow to initiate.

Tarjeta de imagen prominente a través de varios tipos de eventoHero card using various event types

El código siguiente muestra ejemplos que usan varios eventos de tarjeta enriquecida.The following code shows examples using various rich card events.

Para obtener ejemplos de todas las tarjetas disponibles, consulte el ejemplo de uso de tarjetas .For examples of all the available cards, see the Using cards sample.

Cards.csCards.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.csCards.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 adaptableSend an Adaptive Card

Aunque puede usar el generador de mensajes para crear un mensaje que contenga datos adjuntos (de cualquier tipo), una tarjeta adaptativa es un tipo específico de datos adjuntos.While you can use the message factory to create a message that contains an attachment (of any sort), an Adaptive Card is one specific type of attachment. Tenga en cuenta que algunos canales no admiten tarjetas adaptables y los canales que solo pueden admitirlos parcialmente.Note that some channels don't support Adaptive Cards, and channels that do may only partially support them. Por ejemplo, si envía una tarjeta adaptable en Facebook, los botones no funcionarán, pero los textos y las imágenes funcionan bien.For example, if you send an Adaptive Card in Facebook, the buttons won't work while texts and images work well. El generador de mensajes es una clase auxiliar del SDK de bot Framework que se usa para automatizar los pasos de creación.The message factory is a Bot Framework SDK helper class used to automate creation steps for you.

Tarjetas adaptables es el formato de intercambio de tarjeta abierta que permite a los desarrolladores intercambiar el contenido de la interfaz de usuario de una manera habitual y coherente.Adaptive Cards are an open card exchange format enabling developers to exchange UI content in a common and consistent way. Sin embargo, no todos los canales admiten tarjetas adaptables.However, not all channels support Adaptive Cards.

El Diseñador de tarjetas adaptables proporciona una experiencia en tiempo de diseño enriquecida e interactiva para crear tarjetas adaptables.The Adaptive Cards Designer provides a rich, interactive design-time experience for authoring adaptive cards.

Nota

Debe probar esta característica con los canales que el bot usará para determinar si esos canales admiten las tarjetas adaptables.You should test this feature with the channels your bot will use to determine whether those channels support adaptive cards.

Para usar las tarjetas adaptables, no olvide agregar el paquete de NuGet AdaptiveCards.To use Adaptive Cards, be sure to add the AdaptiveCards NuGet package.

El código fuente que se muestra a continuación se basa en el ejemplo Uso de tarjetas.The source code shown here is based on the Using cards sample.

Cards.csCards.cs

En este ejemplo se lee el JSON de la tarjeta adaptable de un archivo y se agrega como datos adjuntos.This example reads the Adaptive Card JSON from a file and adds it as an attachment.

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.Messages can also include multiple attachments in a carousel layout, which places the attachments side by side and allows the user to scroll across.

El código fuente que se muestra a continuación se basa en el ejemplo Uso de tarjetas.The source code shown here is based on the Using cards sample.

Dialogs/MainDialog.csDialogs/MainDialog.cs

En primer lugar, se crea la respuesta y se definen los datos adjuntos como una lista.First, create the reply and define the attachments as a list.

// 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.Then add the attachments and set the layout type to carousel. Aquí se agregan uno cada vez, pero, si quiere, puede manipular la lista para agregar las tarjetas.Here we're adding them one at a time, but feel free to manipulate the list to add the cards however you prefer.

// 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.Once the attachments are added, you can send the reply just like any other.

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

Recursos adicionalesAdditional resources

Consulte el artículo sobre el diseño de la experiencia del usuario para obtener ejemplos de tarjetas disponibles.See the Design the user experience article for examples of available cards.

Para más información sobre el esquema, consulte el esquema de la tarjeta de Bot Framework y la sección sobre la actividad de mensajes del esquema de actividad de Bot Framework.For detailed information on the schema, see the Bot Framework card schema and the message activity section of the Bot Framework Activity schema.

Ejemplo de código para procesar la entrada de tarjeta adaptableCode sample for processing Adaptive Card input

En el ejemplo siguiente se muestra una manera de usar entradas de tarjeta adaptables dentro de una clase de cuadro de diálogo bot.The following sample shows one way to use Adaptive Card inputs within a bot dialog class. Extiende el ejemplo de tarjetas Heroes mediante la validación de la entrada recibida en el campo de texto del cliente que responde.It extends the hero cards sample by validating the input received in the text field from the responding client. Primero debe agregar la funcionalidad de entrada de texto y de botón a la tarjeta adaptativa existente agregando el código siguiente justo antes del corchete final de adaptiveCard.jsactivado, que se encuentra en la carpeta de recursos:You first need to add the text input and button functionality to the existing adaptive card by adding the following code just before the final bracket of adaptiveCard.json, located in the resources folder:

"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"
        }
      ]
    }
  }
]

Tenga en cuenta que el identificador del campo de entrada de texto se establece en "text" .Note that the ID of the text input field is set to "text". Cuando el usuario selecciona Aceptar, el mensaje que genera la tarjeta adaptativa tendrá una propiedad Value que tiene una propiedad denominada "text" que contiene la información que el usuario especificó en el campo de entrada de texto de la tarjeta.When the user selects OK, the message the Adaptive Card generates will have a value property that has a property named "text" which contains the information the user entered in the text input field of the card.

Nuestro validador usa Newtonsoft.js para convertirlo primero en JObject y, a continuación, crear una cadena de texto recortado para la comparación.Our validator uses Newtonsoft.json to first convert this to a JObject, and then create a trimmed text string for comparison. Por tanto, agregue:So add:

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

para MainDialog.CS e instale el último paquete de NuGet estable de Newtonsoft.Jsen.to MainDialog.cs and install the latest stable NuGet package of Newtonsoft.Json. En el código del validador, agregamos el flujo de lógica a los comentarios del código.In the validator code we added the logic flow into the code comments. Este ChoiceValidator método se coloca en el ejemplo using Cards justo después de la llave de cierre pública para la declaración de MainDialog:This ChoiceValidator method is placed into the Using cards sample just after the closed brace public for declaration of 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;
}

Ahora más arriba en el MainDialog cambio de declaración:Now above in the MainDialog declaration change:

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

a:to:

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

Esto invocará el validador para buscar la entrada de tarjeta adaptativa cada vez que se cree un nuevo mensaje de elección.This will invoke your validator to look for Adaptive Card input each time a new choice prompt is created.

Para probar el código, una vez que se haya mostrado una tarjeta adaptativa, seleccione el botón de texto , escriba una selección válida como, por ejemplo, la tarjeta Hero , y seleccione el botón Aceptar .To test your code, once an Adaptive Card has been displayed, select the Text button, Enter a valid selection such as Hero Card then select the OK button.

Probar tarjeta adaptable

  1. La primera entrada se usará para iniciar un nuevo cuadro de diálogo.The first input will be used to start a new dialog.
  2. Vuelva a seleccionar el botón Aceptar y se usará esta entrada para seleccionar una nueva tarjeta.Select the OK button again and this input will be used to select a new card.

Pasos siguientesNext steps