4

I am working on bot using bot framework to create requests. There I need to upload files to support the ticket. I am having a problem getting the exact file path of the file. I am able to get the content URI. How can I get the exact file path like "**C:\Users\j.jobin\Pictures\Mobile\images.jpeg**"

below is the code I am working with

foreach(Attachment file in filesData) {
  context.UserData.SetValue("Attachment", file.ContentUrl);
  string FileURL = file.ContentUrl; // @"C:\Users\j.jobin\Pictures\Mobile\images.jpeg";

  string fileName = file.Name;
  string test = fileName;
  //CreateSR(context);
  string p = FileURL;
  p = new Uri(p).LocalPath;

  string TicketNo = "24712";
  UploadAttchement(TicketNo, p, fileName);
}

The content URI looks something like http://localhost:56057/v3/attachments/479e6660-f6ef-11e8-9659-d50246e856bf/views/original

I tried using string path = Path.GetFullPath(FileName); But that gives the server path (‘C:\Program Files (x86)\IIS Express\tesla-cat.jpg’.) other than a local file path

Jobin Joseph
  • 110
  • 9
  • Possible duplicate of [How to get full file path from file name?](https://stackoverflow.com/questions/13175868/how-to-get-full-file-path-from-file-name) – Hamza Haider Dec 03 '18 at 11:48
  • it is different if the file is uploaded from the server it can get the current directory path through string path = Path.GetFullPath(FileName); But here while uploading I need to get the file path and store it somewhere. – Jobin Joseph Dec 03 '18 at 11:57
  • 3
    if the file is uploaded from client to server, you are sending file with byte array. You either need to save file to your server then get it from disk or the most convenient way would be to directly use stream. – Derviş Kayımbaşıoğlu Dec 03 '18 at 12:14
  • The file should be handled as a stream as the path will be different in case the bot is running on remote machine. The channel should send the file as a stream or attachment – Mandar Dharmadhikari Dec 05 '18 at 00:44

1 Answers1

2

There is no mechanism for retrieving the path for the file on disk, or the local path from where the user uploaded it (this is considered a security risk: how-to-get-full-path-of-selected-file-on-change-of-input-type-file-using-jav ).

The ContentUrl property is http://localhost:56057/v3/attachments/guid/views/original because the bot is connected to the emulator. This path is Bot Framework Channel specific. Your local emulator's server is hosted on port 56057. As stated by Simonare in the comments: you need to download the file, and save it somewhere.

This example demonstrates how to retrieve the bytes of the file: core-ReceiveAttachment

Crudely modified to save multiple files in a local folder: (This is not a good idea in a production scenario, without other safeguards in place. It would be better to upload the bytes to blob storage using Microsoft.WindowsAzure.Storage or something similar.)

if (message.Attachments != null && message.Attachments.Any())
{
    using (HttpClient httpClient = new HttpClient())
    {
        // Skype & MS Teams attachment URLs are secured by a JwtToken, so we need to pass the token from our bot.
        if ((message.ChannelId.Equals(ChannelIds.Skype, StringComparison.InvariantCultureIgnoreCase) 
            || message.ChannelId.Equals(ChannelIds.Msteams, StringComparison.InvariantCultureIgnoreCase)))
        {
            var token = await new MicrosoftAppCredentials().GetTokenAsync();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        }

        foreach (Attachment attachment in message.Attachments)
        {
            using (var responseMessage = await httpClient.GetAsync(attachment.ContentUrl))
            {
                using (var fileStream = await responseMessage.Content.ReadAsStreamAsync())
                {
                    string path = Path.Combine(System.Web.HttpContext.Current.Request.MapPath("~\\Content\\Files"), attachment.Name);
                    using (FileStream file = new FileStream(path, FileMode.Create, FileAccess.Write))
                    {
                        await fileStream.CopyToAsync(file);
                        file.Close();
                    }
                }
                var contentLenghtBytes = responseMessage.Content.Headers.ContentLength;
                await context.PostAsync($"Attachment of {attachment.ContentType} type and size of {contentLenghtBytes} bytes received.");
            }
        }
    }
}

This example for BotBuilder-v4 presents another method: 15.handling-attachments/AttachmentsBot.cs#L204

private static void HandleIncomingAttachment(IMessageActivity activity, IMessageActivity reply)
        {
            foreach (var file in activity.Attachments)
            {
                // Determine where the file is hosted.
                var remoteFileUrl = file.ContentUrl;

                // Save the attachment to the system temp directory.
                var localFileName = Path.Combine(Path.GetTempPath(), file.Name);

                // Download the actual attachment
                using (var webClient = new WebClient())
                {
                    webClient.DownloadFile(remoteFileUrl, localFileName);
                }

                reply.Text = $"Attachment \"{activity.Attachments[0].Name}\"" +
                             $" has been received and saved to \"{localFileName}\"";
            }
        }
Eric Dahlvang
  • 8,252
  • 4
  • 29
  • 50