Receiving files sent to your botframework chatbot

We’ve already looked at how a botframework bot receives messages, and even how to save those messages.

In this article I’ll show you how to handle files that are sent to your botframework chatbot.

When a user interacts with your bot, unless they’re responding to a prompt, they will cause the Message controller’s Post method to fire with an activity.

This will send a message through to your underlying IDialog or LuisDialog implementation.

MessageReceived

The method that receives the message will have the signature (though the parameter names and method name could be different):

public async Task MessageReceived(
                    IDialogContext context, 
                    IAwaitable<IMessageActivity> argument)

We can get the actual message by awaiting the IAwaitable<IMessageActivity>:

var message = await argument;

Now let’s check if the message has any attachments:

if (message.Attachments != null &&
     message.Attachments.Any())

Assuming the message has attachments we can now get the file contents; due to limitations on the total message size, the preferred way to send a file attachment is by using the ContentUrl property:

var attachmentUrl = 
   message.Attachments[0].ContentUrl;

If the file is being passed directly then you can get the data directly from the Content property, which is of type object:

var attachmentData = 
   message.Attachments[0].Content;

Depending on the type of the attachment, this object could be pretty much anything..

The attachment type is in the the ContentType property, which should be a valid mime type, e.g. “image/jpeg” or “audio/mp3”:

var attachmentType = 
   message.Attachments[0].ContentType;

Getting the file!

Most clients will save the file in their own remote hosting service (possibly backed by Amazon S3 or Azure blob storage) and send that hosting service’s URL as the ContentUrl for the attachment.

var attachmentUrl = 
   message.Attachments[0].ContentUrl;

var httpClient = new HttpClient();

var attachmentData = 
    await httpClient.GetByteArrayAsync(attachmentUrl);

Skype (and other client) Attachment Trick

If the client that’s talking to your bot has uploaded the image into a location that requires some form of authentication (such as Skype’s CDN does), then you’ll find a direct HTTP request to the attachment’s URL results in an “access forbidden” error.

You need to set the HTTP request headers to include your bot’s current credentials by creating a ConnectorClient from the message’s ServiceUrl. That ConnectorClient will have a HttpClient property which will be authenticated to access the attachments referenced from the message:

var attachmentUrl = 
   message.Attachments[0].ContentUrl;

var connector = 
    new ConnectorClient(new Uri(message.ServiceUrl));

var attachmentData = 
    connector.HttpClient.GetByteArrayAsync(attachmentUrl).Result;`

Hope you find that useful!

3 thoughts on “Receiving files sent to your botframework chatbot

  1. Hi I’m Sreejit, I’m making a bot which can connect to any news feed like Bing news or google news and give me top 10 news of the day. To be frank I’m not being able to implement it I am very new to this section. Can you please help me with it.

  2. Hi Robin,

    Did you ever saved the attachment, for example into a SQL database, or send the attachment for instance by email to someone? I want to keep the attachment somewhere so it can be used later on. (For example: it’s a chatbot handling complaints. The user wants to illustrate his complaint with an image and sends it via a chatbot. Afterwards the owner of the chatbot wants to handle the complaint and thus needs to see the image + message of user).
    Many thanks in advance. Like you blog posts a lot!

Leave a Reply

Your email address will not be published. Required fields are marked *