(401)从SharePoint

时间:2017-08-14 12:21:20

标签: sharepoint sharepoint-2013 sharepoint-online csom

我使用SharePoint Online服务器的OAuth机制生成了访问令牌。我使用此令牌使用CSOM创建ClientContext。虽然我能够无缝访问所有站点,库和文件夹,但我收到错误

  

远程服务器返回错误:(401)未经授权。

从SharePoint Online下载文件时

。以下是我用于文件下载的代码:

var clientContext = TokenHelper.GetClientContextWithAccessToken("https://adventurer.sharepoint.com/Subsite1", accessToken);
var list = clientContext.Web.Lists.GetByTitle("SubSite 1 Library 1");
string vquery = @"<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='UniqueId' /><Value Type='Lookup'>" + "6718053d-a785-489c-877f-5a4b88dcb2a7" + "</Value></Eq></Where></Query></View>";
CamlQuery query = new CamlQuery();
query.ViewXml = vquery;
var listItems = list.GetItems(query);
clientContext.Load(listItems, items => items.Take(1).Include(item => item.File));
clientContext.ExecuteQuery();

var fileRef = listItems[0].File.ServerRelativeUrl;
var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, fileRef);

我无法理解此错误的根本原因,因为我正在使用正确的访问令牌传递客户端上下文。我想知道OpenBinaryDirect是否有限制使用访问令牌?如果没有,上面的代码有什么问题?是否有其他可用于使用访问令牌下载的替代方案?

2 个答案:

答案 0 :(得分:0)

我正在使用C#,这就是我目前从SharePoint Online检索文档的方式。我在gridview中向用户显示了他们的文档列表,因此我使用文档填充DataTable。我不确定使用访问令牌的方式,但如果您能够像我一样使用服务帐户,那么希望这对您有所帮助。

命名空间

using Microsoft.SharePoint.Client;
using SP = Microsoft.SharePoint.Client;

对象属性

SecureString securePassword = new SecureString();
private string username = "";    
ClientContext context = new SP.ClientContext("https://<root>.sharepoint.com/<site collection (unless root)>/<site>");

构造函数(这是我的身份验证方式)

public SharePoint()
{
    securePassword = convertToSecureString(System.Web.Configuration.WebConfigurationManager.AppSettings["O365PW"]);
    username = System.Web.Configuration.WebConfigurationManager.AppSettings["O365UN"];
    context.Credentials = new SharePointOnlineCredentials(username, securePassword);
}

获取文件的方法

public DataTable GetDocuments(int changeID)
{
    DataTable dt = new DataTable("ChangeDocuments");
    DataRow dr = dt.NewRow();
    dt.Columns.Add("Title");
    dt.Columns.Add("URL");
    dt.Columns.Add("ChangeID");
    dt.Columns.Add("Modified");
    dt.Columns.Add("ID");


    // The SharePoint web at the URL.
    Web web = context.Web;

    // We want to retrieve the web's properties.
    context.Load(web);

    // We must call ExecuteQuery before enumerate list.Fields. 
    context.ExecuteQuery();

   // Assume the web has a list named "Announcements". 
   SP.List oList = context.Web.Lists.GetByTitle("Name of your document library");

   // This creates a CamlQuery that has a RowLimit of 100, and also specifies Scope="RecursiveAll" 
   // so that it grabs all list items, regardless of the folder they are in. 
   CamlQuery query = CamlQuery.CreateAllItemsQuery(100);
query.ViewXml = "<View><Query><Where><Eq><FieldRef Name='ChangeID'/>" +
    "<Value Type='Number'>" + changeID + "</Value></Eq></Where></Query><RowLimit>100</RowLimit></View>";
   SP.ListItemCollection items = oList.GetItems(query);

   // Retrieve all items in the ListItemCollection from List.GetItems(Query). 
   context.Load(items);
   context.ExecuteQuery();

foreach (Microsoft.SharePoint.Client.ListItem listItem in items)
{
    // We have all the list item data. For example, Title. 

    dr = dt.NewRow();

    dr["Title"] = listItem["FileLeafRef"];

    if (String.IsNullOrEmpty(listItem["ServerRedirectedEmbedUrl"].ToString()))
    {
        dr["URL"] = "<root>/<site>/<document library>" + listItem["FileLeafRef"].ToString();
    }
    else
    {
        dr["URL"] = listItem["ServerRedirectedEmbedUrl"];
    }

    dr["ChangeID"] = listItem["ChangeID"];
    dr["Modified"] = Convert.ToDateTime(listItem["Modified"]).ToString("MMM.dd,yyyy h:mm tt");
    dr["ID"] = listItem["ID"];
    dt.Rows.Add(dr);
 }

return dt;
}

将密码转换为安全字符串的方法

private SecureString convertToSecureString(string strPassword)
{
        var secureStr = new SecureString();
        if (strPassword.Length > 0)
        {
            foreach (var c in strPassword.ToCharArray()) secureStr.AppendChar(c);
        }
        return secureStr;
}

答案 1 :(得分:0)

在尝试了很多替代方案后,我得出结论,OpenBinaryDirect()不能用它OAuth令牌。我能够使用其他方法从SharePoint Online下载文件。我在这里发布答案,以便它可以帮助某人:

方法1(OpenBinaryStream):

                var file = clientContext.Web.GetFileByServerRelativeUrl(fileRef);
                clientContext.Load(file);
                clientContext.ExecuteQuery();                    
                ClientResult<Stream> streamResult = file.OpenBinaryStream();
                clientContext.ExecuteQuery();

虽然此方法运行良好,但OpenBinaryStream&lt; = v 14.0.0.0中无法使用Microsoft.SharePoint.Client.dll

方法2(WebClient或其他Http请求):

string downloadUrl = HostURL + "/_api/web/getfilebyserverrelativeurl('" + fileRef + "')/$value";
WebClient client = new WebClient(); 
client.Headers.Add("Authorization", "Bearer " + accessToken);
client.DownloadFile(downloadUrl, filePath);

请注意我用于WebClient的下载URL。普通文件URL无法从SharePoint Online下载文件。