首页 > 解决方案 > 下载从 Sharepoint 上传到 Bot 的图片返回 403 FORBIDDEN

问题描述

我正在使用 Bot Framework v4 SDK。我正在尝试将通过机器人上传到 Microsoft Teams 的图片下载到临时目录中,然后使用该图片。我之所以这样做是因为我需要拍摄一张用户附加到聊天中的照片,然后将这张照片放入文档中并将文档返回给用户。当我在模拟器上运行它时,这可以工作,但是一旦机器人在 Teams 中,我就会收到错误。

我通过 AttachmentPrompt 提示用户输入照片:

return await stepContext.PromptAsync(
    "imagePrompt",
    new PromptOptions
    {
        Prompt = MessageFactory.Text("Please attach a picture."),
    });

从 stepContext.Result 中获取附件:

List<Attachment> contextAttachmentResult = (List<Attachment>)stepContext.Result;

确定文件的托管位置

var remoteFileUrl = contextAttachmentResult[0].ContentUrl;

设置系统临时目录的路径

var tempImagePath = Path.Combine(Path.GetTempPath(), contextAttachmentResult[0].Name);

并尝试使用WebClient

using (var webClient = new WebClient())
{
    webClient.Headers.Add("User-Agent", "Other");
    webClient.Headers.Add("Authorization", userProfile.Token);
    webClient.DownloadFile(remoteFileUrl, tempImagePath);
}

我已经尝试将令牌放入从 中获得的令牌OAuthPrompt,但我仍然得到 403。当我尝试下载它时,就会出现 403。我认为这是 SharePoint 问题的原因是因为如果我打印出来,remoteFileUrl我会得到https://company-my.sharepoint.com/personal/my_name/Documents/Microsoft Teams Chat Files/someImage.png

堆栈跟踪的开头是:

System.Net.WebException: The remote server returned an error: (403) FORBIDDEN. at System.Net.HttpWebRequest.GetResponse() at System.Net.WebClient.GetWebResponse(WebRequest request) at System.Net.WebClient.DownloadBits(WebRequest request, Stream writeStream) at System.Net.WebClient.DownloadFile(Uri address, String fileName)

编辑:根据米克的评论,我试图以ConnectorClient这种方式使用(并尝试两种不同的下载方式):

using (var connectorClient = new ConnectorClient(new Uri(stepContext.Context.Activity.ServiceUrl, MYAPPID, MYAPPPASSWORD)))
{
    var token = await (connectorClient.Credentials as MicrosoftAppCredentials).GetTokenAsync();
    using (var httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contextAttachmentResult[0].ContentType));
        var byteArray = await httpClient.GetByteArrayAsync(remoteFileUrl);

    }
    using (var webClient = new WebClient())
    {
        webClient.Headers.Add("User-Agent", "Other");
        webClient.Headers.Add("Authorization", token);
        webClient.DownloadFile(remoteFileUrl, siteReviewFile1ImagePath);
    }
}

但即使我已将连接器设置为使用我的 appId 和 appPwd,我也会收到 401System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized). at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() at System.Net.Http.HttpClient.d__30.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at IBIBot.Dialogs.SiteReviewSpace.SiteReviewDialog.<>c__DisplayClass4_0.<<-ctor>b__2>d.MoveNext() in

我仍然对如何获取此下载感到困惑

标签: c#.netsharepointbotframework

解决方案


这可以通过不使用 Attachment.ContentUrl 而是使用 Attachment.Content.DownloadUrl 来解决。downloadurl 是预授权下载,因此不需要任何承载或授权标头。我的代码看起来像这样:

var remoteFileUrl = ((JObject)contextAttachmentResult[0].Content)["downloadUrl"].ToString();
using (var webClient = new WebClient())
{
    webClient.DownloadFile(remoteFileUrl, someFileLocationPath);
}

推荐阅读