I have this code in OnTurnAsync()
in the main bot class that let the user upload image and saved it locally and its working fine.
But how can i do this if i want to do it in a different class like a MainDialog class?
Update: I manage to do it by the code below. But it is accepting everything, how can i do a validation that accepts only images?
Update: Answer below.
public class MainDialog : ComponentDialog
{
private const string InitialId = "mainDialog";
private const string TEXTPROMPT = "textPrompt";
private const string ATTACHPROMPT = "attachPrompt";
public MainDialog(string dialogId)
: base(dialogId)
{
WaterfallStep[] waterfallSteps = new WaterfallStep[]
{
FirstStepAsync,
SecondStepAsync,
};
AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
AddDialog(new AttachmentPrompt(ATTACHPROMPT));
}
private static async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
return await stepContext.PromptAsync(
ATTACHPROMPT,
new PromptOptions
{
Prompt = MessageFactory.Text($"upload photo."),
RetryPrompt = MessageFactory.Text($"upload photo pls."),
});
}
private static async Task<DialogTurnResult> SecondStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
var activity = stepContext.Context.Activity;
if (activity.Attachments != null && activity.Attachments.Any())
{
foreach (var file in stepContext.Context.Activity.Attachments)
{
var remoteFileUrl = file.ContentUrl;
var localFileName = Path.Combine(Path.GetTempPath(), file.Name);
using (var webClient = new WebClient())
{
webClient.DownloadFile(remoteFileUrl, localFileName);
}
await stepContext.Context.SendActivityAsync($"Attachment {stepContext.Context.Activity.Attachments[0].Name} has been received and saved to {localFileName}.");
}
}
return await stepContext.EndDialogAsync();
}
Managed to do it with this code.
var activity = stepContext.Context.Activity;
if (activity.Attachments != null && activity.Attachments.Any())
{
foreach (var file in stepContext.Context.Activity.Attachments)
{
if (file.ContentType.EndsWith("/jpg") || file.ContentType.EndsWith("/png") || file.ContentType.EndsWith("/bmp") || file.ContentType.EndsWith("/jpe"))
{
var remoteFileUrl = file.ContentUrl;
var localFileName = Path.Combine(Path.GetTempPath(), file.Name);
using (var webClient = new WebClient())
{
webClient.DownloadFile(remoteFileUrl, localFileName);
}
await stepContext.Context.SendActivityAsync($"Attachment {stepContext.Context.Activity.Attachments[0].Name} has been received and saved to {localFileName}.");
return await stepContext.NextAsync();
}
else
{
await stepContext.Context.SendActivityAsync($"Attachment {file.Name} is not an image, it is {file.ContentType}.");
// restart the dialog from top
return await stepContext.ReplaceDialogAsync(InitialId);
}
}
}
Like Nicolas R said, you could do some basic validation like this:
foreach (var file in activity.Attachments)
{
if (file.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
{
await turnContext.SendActivityAsync($"Attachment {file.Name} is an image of type {file.ContentType}.");
}
else
{
await turnContext.SendActivityAsync($"Attachment {file.Name} is not an image, it is {file.ContentType}.");
}
}
This will of course allow any attachment with a content type that starts with "image/". You might not want to allow any content type that starts with "image/", in which case you'd want to make a list of accepted types like "image/png" and "image/jpeg". You might also consider checking the file extension (to see if it's ".png" or ".jpg" etc.)