C#通过Selenium登录微软账号编辑SharePoint Excel报405错误如何解决
问题根因
你遇到的问题同时包含两个错误点:
- 第一个是上传地址错误:你当前传入的
https://teamsite.xxxxxx.com/:x:/s/test597/xxxxxx-xxxxxxxxx_xxxxxx?e=xxxxx是SharePoint生成的文件预览共享链接,该端点仅支持GET请求,不支持PUT上传操作,这是触发405 Method Not Allowed的核心原因。 - 第二个是身份认证信息缺失:你当前用的
CredentialCache.DefaultCredentials是本地Windows凭据,和Selenium模拟登录得到的微软账号身份完全无关,就算地址正确也会被鉴权拒绝。
修复步骤
- 修正上传路径:将共享链接替换为SharePoint站点内文件的真实路径,格式为
https://<站点域名>/sites/<站点名>/<文档库名>/<目标文件名>.xlsx,比如你要上传到test597站点的共享文档库,路径就是https://teamsite.xxxxxx.com/sites/test597/Shared Documents/exceltest.xlsx - 导出Selenium登录后的Cookie:完成微软账号登录后,先导航到你的SharePoint站点根地址,确保站点相关Cookie全部加载完成,再将Selenium的Cookie集合转换为WebRequest可用的
CookieContainer对象 - 修改上传方法,传入CookieContainer完成身份认证
完整修改后的代码示例
using OpenQA.Selenium; using OpenQA.Selenium.Firefox; using OpenQA.Selenium.Support.UI; using SeleniumExtras.WaitHelpers; using OtpNet; using System.Net; using System.IO; static void Main(string[] args) { string base32Secret = "xxxxxxx"; var secret = Base32Encoding.ToBytes(base32Secret); var totp = new Totp(secret); var code = totp.ComputeTotp(); Console.WriteLine(code); IWebDriver driver = new FirefoxDriver(); driver.Navigate().GoToUrl("https://myaccount.microsoft.com/"); // 用户名输入 WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); wait.Until(ExpectedConditions.ElementIsVisible(By.Id("i0116"))); driver.FindElement(By.Id("i0116")).SendKeys("xxxxx"); driver.FindElement(By.Id("idSIButton9")).Click(); // 密码输入 wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); wait.Until(ExpectedConditions.ElementIsVisible(By.Id("i0118"))); driver.FindElement(By.Id("i0118")).SendKeys("xxxxxxx"); driver.FindElement(By.Id("idSIButton9")).Click(); // OTP输入 wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); wait.Until(ExpectedConditions.ElementIsVisible(By.Id("idTxtBx_SAOTCC_OTC"))); driver.FindElement(By.Id("idTxtBx_SAOTCC_OTC")).SendKeys(code); driver.FindElement(By.Id("idSubmit_SAOTCC_Continue")).Click(); // 保持登录确认 wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); wait.Until(ExpectedConditions.ElementIsVisible(By.Id("idSIButton9"))); driver.FindElement(By.Id("idSIButton9")).Click(); // 新增:导航到SharePoint站点加载站点Cookie driver.Navigate().GoToUrl("https://teamsite.xxxxxx.com/s/test597/"); wait.Until(d => d.Title.Contains("test597")); // 等待站点加载完成 // 新增:导出Selenium Cookie到CookieContainer CookieContainer cookieContainer = new CookieContainer(); foreach (var cookie in driver.Manage().Cookies.AllCookies) { cookieContainer.Add(new System.Net.Cookie( cookie.Name, cookie.Value, cookie.Path, cookie.Domain )); } driver.Quit(); // 登录完成可以关闭浏览器了 // 修正:传入CookieContainer,替换为真实的上传路径 PublishWorkbook( @"C:\test\exceltest.xlsx", "https://teamsite.xxxxxx.com/sites/test597/Shared Documents/exceltest.xlsx", cookieContainer ); } // 新增:方法增加CookieContainer参数 static void PublishWorkbook(string LocalPath, string SharePointPath, CookieContainer cookieContainer) { WebResponse response = null; try { WebRequest request = WebRequest.Create(SharePointPath); // 删掉原来的DefaultCredentials,替换为CookieContainer request.CookieContainer = cookieContainer; request.Method = "PUT"; byte[] buffer = new byte[1024]; using (Stream stream = request.GetRequestStream()) using (FileStream fsWorkbook = File.Open(LocalPath, FileMode.Open, FileAccess.Read)) { int i = fsWorkbook.Read(buffer, 0, buffer.Length); while (i > 0) { stream.Write(buffer, 0, i); i = fsWorkbook.Read(buffer, 0, buffer.Length); } } response = request.GetResponse(); } finally { response?.Close(); // 增加空判断避免空引用异常 } }
注意事项
- 确保你登录的微软账号对目标SharePoint文档库有编辑/上传权限
- 如果要上传到子文件夹,直接在路径里拼接子文件夹名称即可
- 如果需要避免覆盖已有文件,可以在请求头中添加
If-Match: *或者对应文件的ETag值控制行为
内容的提问来源于stack exchange,提问作者pasta1248
相关产品推荐
相关产品推荐

