How to save files to Azure File Share from Bot Framework Composer

Viewed 33

I created bot using Bot Framework SDK that saves the files uploaded by user to Azure File Share. Here is the code that saves the files to Azure File Share.

using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
using System;
using System.Linq;
using System.IO;
using Azure.Storage.Files.Shares;
using Azure;
using System.Net.Http;

namespace CallSDKBot.MigratedDialogs
{
public class FileHandlerBot: ActivityHandler
{
    protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
    {
        await SendWelcomeMessageAsync(turnContext, cancellationToken);
    }

    // Greet the user and give them instructions on how to interact with the bot.
    private static async Task SendWelcomeMessageAsync(ITurnContext turnContext, CancellationToken cancellationToken)
    {
        foreach (var member in turnContext.Activity.MembersAdded)
        {
            if (member.Id != turnContext.Activity.Recipient.Id)
            {
                await turnContext.SendActivityAsync(
                    $"From SDK Bot - Welcome!" + Environment.NewLine.ToString() + 
                    $" This bot will allow you to upload Attachments." +
                    $" Click on paper clip to upload one or more files. ",
                    cancellationToken: cancellationToken);
            }
        }
    }

    protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
    {
        var reply = await ProcessInput(turnContext, cancellationToken);
        
        // Respond to the user.
        await turnContext.SendActivityAsync(reply, cancellationToken);
    }


    private static async Task<IMessageActivity> ProcessInput(ITurnContext turnContext, CancellationToken cancellationToken)
    {
        var activity = turnContext.Activity;
        IMessageActivity reply = null;

        if (activity.Attachments != null && activity.Attachments.Any())
        {
            reply = await HandleIncomingAttachmentAsync(activity);
        }

        return await Task.FromResult(reply);
    }

    private static async Task<IMessageActivity> HandleIncomingAttachmentAsync(IMessageActivity activity)
    {
        var replyText = string.Empty;
        foreach (var file in activity.Attachments)
        {
            var remoteFileUrl = file.ContentUrl;

            // Full path to users local temp file folder
            string myTempFile = Path.Combine(Path.GetTempPath(), file.Name);

            var httpClient = new HttpClient();

            using (Stream stream = await httpClient.GetStreamAsync(remoteFileUrl).ConfigureAwait(false))
            {
                using FileStream fileStream = new(myTempFile, FileMode.Create);
                stream.CopyTo(fileStream);
            }

            //code starts here to store files to Azure File Share
            string connectionString = "<connectionstring>";

            // Name of the Azure share, directory, and file 
            string shareName = "fileuploads";
            string dirName = "test";
            string fileName = file.Name;

            //Azure FileShare
            ShareClient share = new ShareClient(connectionString, shareName);

            // Get a reference to a directory
            ShareDirectoryClient directory = share.GetDirectoryClient(dirName);

            ShareFileClient f = directory.GetFileClient(fileName);

            using (var stream = File.OpenRead(myTempFile))
            {
                f.Create(stream.Length);
                f.UploadRange(
                    new HttpRange(0, stream.Length),
                    stream);
            }
            //code ends here to store files to Azure File Share

            replyText += $"Attachment \"{file.Name}\" has been received and saved." + Environment.NewLine.ToString();
        }

        return await Task.FromResult((IMessageActivity)MessageFactory.Text(replyText));
    }
}
}

Then I created another bot using Framework Composer. I’m not able to figure out how to migrate the above code to Composer bot so that I can save the file anytime user uploads a file during the conversation.

1 Answers

The standard way to add new functionality to Composer is through the use of custom actions.

Essentially you write the new functionality in code (or reuse existing code, whatever the case may be) and then call it from the Composer build canvas as you would a built-in action. The linked documentation shows you how to create and add an example C# custom action to a Composer bot. There is also a custom action sample.

Related