使用HttpClient上传文件至SharePoint Online Drive时程序无响应求助
问题分析与解决方案
核心原因:异步操作未被主线程等待,导致程序提前退出
你的控制台程序中,若Main方法是普通void类型,执行到await client.PutAsync时,异步操作会在后台运行,但主线程不会等待其完成,直接走到代码末尾后程序正常退出(返回码0),因此看不到任何日志输出,文件上传也未完成。
另外代码存在一处明显错误:你给获取令牌时使用的content对象设置了ContentType,而非要上传的fileContent,这会导致请求的内容类型不正确,即便解决了异步等待问题,也可能上传失败。
修复步骤
- 将
Main方法改为异步类型:把控制台程序的Main方法声明为async Task Main(),确保主线程会等待所有异步操作完成。 - 替换同步阻塞的
.Result为await:避免同步阻塞引发死锁,同时保证异步流程的正确性。 - 修正
ContentType的赋值对象:给fileContent设置正确的内容类型。 - 添加控制台暂停(可选):防止程序执行完成后直接关闭控制台,方便查看输出结果。
修正后的完整代码示例
using System; using System.IO; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using Newtonsoft.Json; class Program { static async Task Main(string[] args) { var tokenEndpoint = "你的令牌请求端点"; var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("grant_type", "client_credentials"), // 补充client_id、client_secret等必要参数 }); var httpClient = new HttpClient(); var response = await httpClient.PostAsync(tokenEndpoint, content); response.EnsureSuccessStatusCode(); // 确保令牌请求成功 var token = await response.Content.ReadAsStringAsync(); var accessToken = JsonConvert.DeserializeObject<AccessToken>(token).access_token; var fileName = @"c:\data\sample.txt"; var fileNameEndpoint = @"https://graph.microsoft.com/v1.0/drives/{driveID}/root:/General/sample.txt:/content"; using (HttpClient client = new HttpClient()) { using (FileStream fileStream = File.OpenRead(fileName)) { var fileContent = new StreamContent(fileStream); fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); try { var response1 = await client.PutAsync(fileNameEndpoint, fileContent); if (response1.IsSuccessStatusCode) { Console.WriteLine("文件上传成功!"); } else { // 读取详细错误信息,便于排查问题 var errorContent = await response1.Content.ReadAsStringAsync(); Console.WriteLine($"错误:{response1.StatusCode} - {response1.ReasonPhrase}\n详情:{errorContent}"); } } catch (Exception e) { Console.WriteLine($"发生异常:{e.Message}\n堆栈跟踪:{e.StackTrace}"); throw; } } } Console.WriteLine("按任意键退出..."); Console.ReadKey(); } } public class AccessToken { public string access_token { get; set; } // 可添加expires_in等其他返回属性 }
额外建议
- 获取令牌后添加
response.EnsureSuccessStatusCode()检查请求是否成功,避免使用无效令牌调用Graph API。 - 上传失败时读取响应的详细内容,能获取Graph API返回的具体错误信息,大幅提升排查效率。
内容的提问来源于stack exchange,提问作者gilesrpa
相关产品推荐
相关产品推荐

