How to get attachment uploaded by bot user - c#

public virtual async Task MotgaAtt(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var message = await argument;
if (message.Attachments != null && message.Attachments.Any())
{
var attachment = message.Attachments.First();
using (HttpClient httpClient = new HttpClient())
{
var responseMessage = await httpClient.GetAsync(attachment.ContentUrl);
var contentLenghtBytes = responseMessage.Content.Headers.ContentLength;
await context.PostAsync($"Attachment of {attachment.ContentType} type and size of {contentLenghtBytes} bytes received.");
}
}
context.Done<object>(new object());
}
I want to get the uploaded attachment by the bot user so i can insert it in the database. I tried to use the attachment variable i created but it seems not to be the exact file the user uploaded. Please how do i get the uploaded file?. Thanks

See official samples: https://github.com/Microsoft/BotBuilder-Samples/tree/master/CSharp/core-ReceiveAttachment
Depending on the channel you must give a specific token:
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var message = await argument;
if (message.Attachments != null && message.Attachments.Any())
{
var attachment = message.Attachments.First();
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("skype", StringComparison.InvariantCultureIgnoreCase) || message.ChannelId.Equals("msteams", StringComparison.InvariantCultureIgnoreCase))
&& new Uri(attachment.ContentUrl).Host.EndsWith("skype.com"))
{
var token = await new MicrosoftAppCredentials().GetTokenAsync();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
var responseMessage = await httpClient.GetAsync(attachment.ContentUrl);
var contentLenghtBytes = responseMessage.Content.Headers.ContentLength;
await context.PostAsync($"Attachment of {attachment.ContentType} type and size of {contentLenghtBytes} bytes received.");
}
}
else
{
await context.PostAsync("Hi there! I'm a bot created to show you how I can receive message attachments, but no attachment was sent to me. Please, try again sending a new message including an attachment.");
}
context.Wait(this.MessageReceivedAsync);
}

Related

How to read attachment content from bot framework C#?

I am writing a bot and expecting the user to send me an attachment, which I want to read and translate into objects.
I have the following code so far:
if (message.Attachments != null && message.Attachments.Any())
{
var attachment = message.Attachments.First();
using (HttpClient httpClient = new HttpClient())
{
if ((message.ChannelId.Equals("skype", StringComparison.InvariantCultureIgnoreCase) || message.ChannelId.Equals("msteams", StringComparison.InvariantCultureIgnoreCase)) && new Uri(attachment.ContentUrl).Host.EndsWith("skype.com"))
{
var token = await new MicrosoftAppCredentials().GetTokenAsync();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
var responseMessage = await httpClient.GetAsync(attachment.ContentUrl);
var contentLenghtBytes = responseMessage.Content.Headers.ContentLength; // this is populated correctly
if(attachment.Name.ToLower().Equals("opportunity.xlsx"))
{
var temp = attachment.Content; // This Content is always null, even though everything else is populated.
}
}
}
Anyone can suggest how can I read the attachment xlsx content please?
Thanks
The attachment is not available in the Content property. You first need to download the attachment using the ContentUrl and then perform whatever you want, using the response message after downloading the file.
Take a look at the Receive-Attachments C# sample.
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var message = await argument;
if (message.Attachments != null && message.Attachments.Any())
{
var attachment = message.Attachments.First();
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("skype", StringComparison.InvariantCultureIgnoreCase) || message.ChannelId.Equals("msteams", StringComparison.InvariantCultureIgnoreCase))
&& new Uri(attachment.ContentUrl).Host.EndsWith("skype.com"))
{
var token = await new MicrosoftAppCredentials().GetTokenAsync();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
var responseMessage = await httpClient.GetAsync(attachment.ContentUrl);
var contentLenghtBytes = responseMessage.Content.Headers.ContentLength;
await context.PostAsync($"Attachment of {attachment.ContentType} type and size of {contentLenghtBytes} bytes received.");
}
}
else
{
await context.PostAsync("Hi there! I'm a bot created to show you how I can receive message attachments, but no attachment was sent to me. Please, try again sending a new message including an attachment.");
}
context.Wait(this.MessageReceivedAsync);
}
You will have to use some other dll to read the excel data, if that is what you mean. Do u mean to read the contents of the excel file after it has been uploded then you could use https://github.com/ExcelDataReader/ExcelDataReader

Incorrect file recieved when user replies with attachment

My bot prompts the user for an attachment in a dialog and is suppose to receive an image from the user and save the content name, url and type of that file to variables. However, the file I am receiving is not the file the user sent. Instead its retrieving a file named 'blob' (no extension) from this link:
https://webchat.botframework.com/attachments/GkLhiqJcvH019mP0iGBKvo/0000052/0/blob?t=X5ICiUrhFas.dAA.RwBrAEwAaABpAHEASgBjAHYASAAwADEAOQBtAFAAMABpAEcAQgBLAHYAbwAtADAAMAAwADAAMAA1ADIA.mcEiHxuH0gE.VMcp6Yduqgc.4xT1ZTOvCX-B7A0nLto6eZNFrFi-0xSzGk5AKmA-EPE
That file contains:
{"type":"message","from":{"id":"9n0I1ZqSrLF","name":"You"},"locale":"en-US","timestamp":"2017-02-14T21:12:32.074Z","channelData":{"clientActivityId":"1487106689866.9060198022610071.8"}}
Here is the code for the attachment prompt. This prompt is within a dialog:
private async Task getAttach(IDialogContext context, IAwaitable<IEnumerable<Attachment>> result)
{
IEnumerable<Attachment> list = await result;
Attachment attachment = list.FirstOrDefault();
string filename = attachment.Name;
string url = attachment.ContentUrl;
string contentType = attachment.ContentType;
//Set attachmentFileNames
if (attachmentFileNames == null)
{
attachmentFileNames = "";
}
attachmentFileNames += contentType;
attachmentFileNames += ",";
numberOfFiles++;
//Set attachmentFileURLs
if (attachmentFileURLs == null)
{
attachmentFileURLs = "";
}
attachmentFileURLs += url;
attachmentFileURLs += ",";
attachmentHasBeenAdded = true;
await FirstMessageReceivedAsync(context, result);
}
Here is how I am handling attachments in the message controller. This is within the Post Task:
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
if (activity.Attachments != null && activity.Attachments.Any())
{
hasaAttachment = true;
var attachment = activity.Attachments.First();
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 ((activity.ChannelId.Equals("skype", StringComparison.InvariantCultureIgnoreCase) || activity.ChannelId.Equals("msteams", StringComparison.InvariantCultureIgnoreCase))
&& new Uri(attachment.ContentUrl).Host.EndsWith("skype.com"))
{
var token = await new MicrosoftAppCredentials().GetTokenAsync();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
var responseMessage = await httpClient.GetAsync(attachment.ContentUrl);
var contentLenghtBytes = responseMessage.Content.Headers.ContentLength;
Activity reply = activity.CreateReply($"Attachment of {attachment.ContentType} type and size of {contentLenghtBytes} bytes received. URL: {attachment.ContentUrl}");
await connector.Conversations.ReplyToActivityAsync(reply);
}
}
I am following this example:
Receive Attachment Bot Sample
In the emulator it works correctly but the published version on azure does not. The code is very similar to the example so I don't see why the bot is not detecting the user's files.
How do I receive the correct file (the file the user replied with)?
The attachments will be in elements 1 onwards. E.g.
Attachment attachment = list.ElementAt(1);
The webchat (and maybe other platforms) has a weird quirk where it adds a blob file at the start of IEnumerable 'result' when prompting and getting attachments from the user.
private async Task getAttach(IDialogContext context, IAwaitable<IEnumerable<Attachment>> result)
{...}

Upload image to Skype BOT

I have a bot develop with Microsoft Bot Framework, and in Debug run correctly
After the install on Skype, after the upload the image I have a link like this
https://df-apis.skype.com/v2/attachments/0-eus-d4-7e19a097c62f5fc21dd53eabfa19d85e/views/original
The code is very simply and run without skype
if ((activity.Attachments != null) && (activity.Attachments.Count > 0))
{
analysisResult = await AnalyzeUrl(activity.Attachments[0].ContentUrl);
}
........
How do I find the picture that I sent?
According to this comment, to fetch an attachment, the GET request should contain JwtToken of the bot as authorization header:
var attachment = activity.Attachments?.FirstOrDefault();
if (attachment?.ContentUrl != null)
{
using (var connectorClient = new ConnectorClient(new Uri(activity.ServiceUrl)))
{
var token = await (connectorClient.Credentials as MicrosoftAppCredentials).GetTokenAsync();
var uri = new Uri(attachment.ContentUrl);
using (var httpClient = new HttpClient())
{
if (uri.Host.EndsWith("skype.com") && uri.Scheme == Uri.UriSchemeHttps)
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
}
else
{
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(attachment.ContentType));
}
var attachmentData = await httpClient.GetByteArrayAsync(uri);
analysisResult = await AnalyzeUrl(attachmentData);
}
}
}
That means you have to change the AnalyzeUrl to accept the image data instead of URL. I believe CognitiveServices, you are using, are able to accept the image data.

Upload file to Pushbullet in Windows 10 app c#

I'm currently using Pushbullet API and need to upload a file.
I can successfully get an upload url as specified in the docs using this method:
public static async Task<Uploads> GetUploadUrl(string file_name, string file_type)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Access-Token", AccessToken);
var json = new JObject
{
["file_name"] = file_name,
["file_type"] = file_type
};
var result = await client.PostAsync(new Uri(_uploadUrl, UriKind.RelativeOrAbsolute), new HttpStringContent(json.ToString(), UnicodeEncoding.Utf8, "application/json"));
if (result.IsSuccessStatusCode)
{
var textresult = await result.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<Uploads>(textresult);
}
}
return null;
}
The problem is when I try to upload the file. I'm currently using this method:
public static async Task<bool> UploadFile(StorageFile file, string upload_url)
{
try
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
var content = new MultipartFormDataContent();
if (file != null)
{
var streamData = await file.OpenReadAsync();
var bytes = new byte[streamData.Size];
using (var dataReader = new DataReader(streamData))
{
await dataReader.LoadAsync((uint)streamData.Size);
dataReader.ReadBytes(bytes);
}
var streamContent = new ByteArrayContent(bytes);
content.Add(streamContent);
}
client.DefaultRequestHeaders.Add("Access-Token", AccessToken);
var response = await client.PostAsync(new Uri(upload_url, UriKind.Absolute), content);
if (response.IsSuccessStatusCode)
return true;
}
catch { return false; }
return false;
}
but I get a Http 400 error. What's the right way to upload a file using multipart/form-data in a UWP app?
HTTP 400 error indicates Bad Request, it means the request could not be understood by the server due to malformed syntax. In the other word, the request sent by the client doesn't follow server's rules.
Let's look at the document, and we can find in the example request it uses following parameter:
-F file=#cat.jpg
So in the request, we need to set the name for the uploaded file and the name should be "file". Besides, in this request, there is no need to use access token. So you can change your code like following:
public static async Task<bool> UploadFile(StorageFile file, string upload_url)
{
try
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
var content = new MultipartFormDataContent();
if (file != null)
{
var streamData = await file.OpenReadAsync();
var bytes = new byte[streamData.Size];
using (var dataReader = new DataReader(streamData))
{
await dataReader.LoadAsync((uint)streamData.Size);
dataReader.ReadBytes(bytes);
}
var streamContent = new ByteArrayContent(bytes);
content.Add(streamContent, "file");
}
//client.DefaultRequestHeaders.Add("Access-Token", AccessToken);
var response = await client.PostAsync(new Uri(upload_url, UriKind.Absolute), content);
if (response.IsSuccessStatusCode)
return true;
}
catch { return false; }
return false;
}
Then your code should be able to work. You will get a 204 No Content response and UploadFile method will return true.

Bot Framework - return Image

I use windows7 Professional and other Bot run without problem.
I want to return an image to my BOT, but the code suggested by Microsoft guide doesn't run
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity reply = activity.CreateReply( $" Hello");
reply.Attachments.Add(new Attachment()
{
ContentUrl = $"https://upload.wikimedia.org/wikipedia/en/a/a6/Bender_Rodriguez.png",
ContentType = "image/png",
Name = "Bender_Rodriguez.png"
});
await connector.Conversations.ReplyToActivityAsync(reply);
}
else
{
HandleSystemMessage(activity);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
I tried this code with Bot Emulator and got the following error:
You need to initialize the Attachments array. In your code, it's null so the Add call is causing a NULL ref exception.
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity reply = activity.CreateReply($" Hello");
reply.Attachments = new List<Attachment>(); //****** INIT
reply.Attachments.Add(new Attachment()
{
ContentUrl = $"https://upload.wikimedia.org/wikipedia/en/a/a6/Bender_Rodriguez.png",
ContentType = "image/png",
Name = "Bender_Rodriguez.png"
});
await connector.Conversations.ReplyToActivityAsync(reply);
}
else
{
HandleSystemMessage(activity);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
You have to add these lines of code after reply activity initialization.
reply.Attachments = new List<Attachment>();
reply.Recipient = activity.From;
reply.Type = "message";
You can refer this link for more details
downloading file (pdf/image) from using Microsoft bot framework

Categories