2
votes

I am using .net 4.8 WebClient and the Microsoft.SharePointOnline.CSOM package, trying to download files from SharePoint online.

const string username = "[email protected]";
const string password = "mypassword";
const string url = "https://tenant.sharepoint.com/:b:/r/filepath.pdf";
var securedPassword = new SecureString();
foreach (var c in password.ToCharArray())
{
    securedPassword.AppendChar(c);
}
var credentials = new SharePointOnlineCredentials(username, securedPassword);
using (var client = new WebClient())
{
    client.Credentials = credentials;
    client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
    client.DownloadFile(url, "C:\\temp\\test.pdf"); //this file path definitely exists
}

The error I get is a 401 unauthorized. I logged out and logged into the SharePoint environment using the same credentials, to ensure that they are correct.

I've tried adding a couple different user agents in the header to see if that helps.

client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
//or
client.Headers.Add("User-Agent: Other");

But it didn't make any difference.

This is similar to Download File From SharePoint 365 which is using what looks like the same code as I am, but Download Document from SharePoint Online using c# webclient stopped working suggests that something has changed and this form of authentication no longer works for connecting to SharePoint online. However I have been unable to find any recent documentation on what we're supposed to use now.

1

1 Answers

0
votes

You could refer to the code provided by official document.
https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest
As I test,it works well.

public static void DownloadFileViaRestAPI(string webUrl, ICredentials credentials, string documentLibName, string fileName, string path)
        {
            webUrl = webUrl.EndsWith("/") ? webUrl.Substring(0, webUrl.Length - 1) : webUrl;
            string webRelativeUrl = null;
            if (webUrl.Split('/').Length > 3)
            {
                webRelativeUrl = "/" + webUrl.Split(new char[] { '/' }, 4)[3];
            }
            else
            {
                webRelativeUrl = "";
            }

            using (WebClient client = new WebClient())
            {
                client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
                client.Credentials = credentials;
                Uri endpointUri = new Uri(webUrl + "/_api/web/GetFileByServerRelativeUrl('" + webRelativeUrl + "/" + documentLibName + "/" + fileName + "')/$value");

                byte[] data = client.DownloadData(endpointUri);
                FileStream outputStream = new FileStream(path + fileName, FileMode.OpenOrCreate | FileMode.Append, FileAccess.Write, FileShare.None);
                outputStream.Write(data, 0, data.Length);
                outputStream.Flush(true);
                outputStream.Close();
            }
        }

        static void Main(string[] args)
        {
            string siteURL = "https://contoso.sharepoint.com/sites/dev";

            //set credential of SharePoint online
            SecureString secureString = new SecureString();
            foreach (char c in "password".ToCharArray())
            {
                secureString.AppendChar(c);
            }
            ICredentials credentials = new Microsoft.SharePoint.Client.SharePointOnlineCredentials("[email protected]", secureString);

            //set credential of SharePoint 2013(On-Premises)
            //string userName = "Administrator";
            //string password = "xxxxxxx";
            //string domain = "CONTOSO";
            //ICredentials credentials = new NetworkCredential(userName, password, domain);

            DownloadFileViaRestAPI(siteURL, credentials, "lib", "test.css", "c:\\SPFX\\");

            Console.WriteLine("success");
            Console.ReadLine();
        }