在瀑布对话框中接受附件并将它们本地存储在 bot 框架 v4 中
Accepting attachments on a waterfall dialog and storing them locally in bot framework v4
我试图添加一个功能来从用户那里获取输入附件,基本上是试图合并来自 bot 框架的 handling-attachments bot 示例和我的自定义瀑布对话框。
但是如何在瀑布对话框中访问 iturncontext 函数? .下面是我的代码的解释。
我的瀑布步之一:
private async Task<DialogTurnResult> DescStepAsync2(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["Title"] = (string)stepContext.Result;
await stepContext.Context.SendActivityAsync(MessageFactory.Text("upload a image"), cancellationToken);
var activity = stepContext.Context.Activity;
if (activity.Attachments != null && activity.Attachments.Any())
{
Activity reply = (Activity)HandleIncomingAttachment(stepContext.Context.Activity);
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = reply }, cancellationToken);
}
else
{
var reply = MessageFactory.Text("else image condition thrown");
// reply.Attachments.Add(Cards.GetHeroCard().ToAttachment());
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = reply }, cancellationToken);
}
}
这是我从上面链接的机器人生成器示例中借用的 HandleIncomingAttachment 函数。
private static IMessageActivity HandleIncomingAttachment(IMessageActivity activity)
{
string replyText = string.Empty;
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);
}
replyText += $"Attachment \"{file.Name}\"" +
$" has been received and saved to \"{localFileName}\"\r\n";
}
return MessageFactory.Text(replyText);
}
以下是对话记录:
编辑:
我已经为此编辑了我的代码,它仍然不等我上传附件。只是完成了这一步。
private async Task<DialogTurnResult> DescStepAsync2(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["Desc"] = (string)stepContext.Result;
var reply = (Activity)ProcessInput(stepContext.Context);
return await stepContext.PromptAsync(nameof(AttachmentPrompt), new PromptOptions { Prompt = reply }, cancellationToken);
}
处理输入函数:
private static IMessageActivity ProcessInput(ITurnContext turnContext)
{
var activity = turnContext.Activity;
IMessageActivity reply = null;
if (activity.Attachments != null && activity.Attachments.Any())
{
// We know the user is sending an attachment as there is at least one item .
// in the Attachments list.
reply = HandleIncomingAttachment(activity);
}
else
{
reply = MessageFactory.Text("No attachement detected ");
// Send at attachment to the user.
}
return reply;
}
一个WaterfallStepContext
inherits from DialogContext
and therefore the ITurnContext
can be accessed through its Context
属性。您发布的瀑布步骤代码在使用 stepContext.Context.SendActivityAsync
或 stepContext.Context.Activity
.
时已经执行此操作
所以我想通了,多亏了这个post:github。com/microsoft/botframework-sdk/issues/5312
我的代码现在的样子:
声明附件提示:
public class CancelDialog : ComponentDialog
{
private static string attachmentPromptId = $"{nameof(CancelDialog)}_attachmentPrompt";
public CancelDialog()
: base(nameof(CancelDialog))
{
// This array defines how the Waterfall will execute.
var waterfallSteps = new WaterfallStep[]
{
TitleStepAsync,
DescStepAsync,
// AskForAttachmentStepAsync,
UploadAttachmentAsync,
UploadCodeAsync,
SummaryStepAsync,
};
// Add named dialogs to the DialogSet. These names are saved in the dialog state.
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
AddDialog(new TextPrompt(nameof(TextPrompt)));
AddDialog(new NumberPrompt<int>(nameof(NumberPrompt<int>), AgePromptValidatorAsync));
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
AddDialog(new AttachmentPrompt(attachmentPromptId));
在瀑布中请求附件提示:
private async Task<DialogTurnResult> UploadAttachmentAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["desc"] = (string)stepContext.Result;
// if ((bool)stepContext.Result)
{
return await stepContext.PromptAsync(
attachmentPromptId,
new PromptOptions
{
Prompt = MessageFactory.Text($"Can you upload a file?"),
});
}
//else
//{
// return await stepContext.NextAsync(-1, cancellationToken);
//}
}
正在处理文件并存储它:
private async Task<DialogTurnResult> UploadCodeAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
List<Attachment> attachments = (List<Attachment>)stepContext.Result;
string replyText = string.Empty;
foreach (var file in 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);
}
replyText += $"Attachment \"{file.Name}\"" +
$" has been received and saved to \"{localFileName}\"\r\n";
}}
希望你有一个想法。
谢谢@Kyle 和@Michael
我试图添加一个功能来从用户那里获取输入附件,基本上是试图合并来自 bot 框架的 handling-attachments bot 示例和我的自定义瀑布对话框。
但是如何在瀑布对话框中访问 iturncontext 函数? .下面是我的代码的解释。
我的瀑布步之一:
private async Task<DialogTurnResult> DescStepAsync2(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["Title"] = (string)stepContext.Result;
await stepContext.Context.SendActivityAsync(MessageFactory.Text("upload a image"), cancellationToken);
var activity = stepContext.Context.Activity;
if (activity.Attachments != null && activity.Attachments.Any())
{
Activity reply = (Activity)HandleIncomingAttachment(stepContext.Context.Activity);
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = reply }, cancellationToken);
}
else
{
var reply = MessageFactory.Text("else image condition thrown");
// reply.Attachments.Add(Cards.GetHeroCard().ToAttachment());
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = reply }, cancellationToken);
}
}
这是我从上面链接的机器人生成器示例中借用的 HandleIncomingAttachment 函数。
private static IMessageActivity HandleIncomingAttachment(IMessageActivity activity)
{
string replyText = string.Empty;
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);
}
replyText += $"Attachment \"{file.Name}\"" +
$" has been received and saved to \"{localFileName}\"\r\n";
}
return MessageFactory.Text(replyText);
}
以下是对话记录:
编辑: 我已经为此编辑了我的代码,它仍然不等我上传附件。只是完成了这一步。
private async Task<DialogTurnResult> DescStepAsync2(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["Desc"] = (string)stepContext.Result;
var reply = (Activity)ProcessInput(stepContext.Context);
return await stepContext.PromptAsync(nameof(AttachmentPrompt), new PromptOptions { Prompt = reply }, cancellationToken);
}
处理输入函数:
private static IMessageActivity ProcessInput(ITurnContext turnContext)
{
var activity = turnContext.Activity;
IMessageActivity reply = null;
if (activity.Attachments != null && activity.Attachments.Any())
{
// We know the user is sending an attachment as there is at least one item .
// in the Attachments list.
reply = HandleIncomingAttachment(activity);
}
else
{
reply = MessageFactory.Text("No attachement detected ");
// Send at attachment to the user.
}
return reply;
}
一个WaterfallStepContext
inherits from DialogContext
and therefore the ITurnContext
can be accessed through its Context
属性。您发布的瀑布步骤代码在使用 stepContext.Context.SendActivityAsync
或 stepContext.Context.Activity
.
所以我想通了,多亏了这个post:github。com/microsoft/botframework-sdk/issues/5312
我的代码现在的样子:
声明附件提示:
public class CancelDialog : ComponentDialog
{
private static string attachmentPromptId = $"{nameof(CancelDialog)}_attachmentPrompt";
public CancelDialog()
: base(nameof(CancelDialog))
{
// This array defines how the Waterfall will execute.
var waterfallSteps = new WaterfallStep[]
{
TitleStepAsync,
DescStepAsync,
// AskForAttachmentStepAsync,
UploadAttachmentAsync,
UploadCodeAsync,
SummaryStepAsync,
};
// Add named dialogs to the DialogSet. These names are saved in the dialog state.
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
AddDialog(new TextPrompt(nameof(TextPrompt)));
AddDialog(new NumberPrompt<int>(nameof(NumberPrompt<int>), AgePromptValidatorAsync));
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
AddDialog(new AttachmentPrompt(attachmentPromptId));
在瀑布中请求附件提示:
private async Task<DialogTurnResult> UploadAttachmentAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["desc"] = (string)stepContext.Result;
// if ((bool)stepContext.Result)
{
return await stepContext.PromptAsync(
attachmentPromptId,
new PromptOptions
{
Prompt = MessageFactory.Text($"Can you upload a file?"),
});
}
//else
//{
// return await stepContext.NextAsync(-1, cancellationToken);
//}
}
正在处理文件并存储它:
private async Task<DialogTurnResult> UploadCodeAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
List<Attachment> attachments = (List<Attachment>)stepContext.Result;
string replyText = string.Empty;
foreach (var file in 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);
}
replyText += $"Attachment \"{file.Name}\"" +
$" has been received and saved to \"{localFileName}\"\r\n";
}}
希望你有一个想法。 谢谢@Kyle 和@Michael