You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编写控制台程序上传PDF至D365时遇FileStream读取异常求助

问题分析与解决方案

问题根源

你遇到的ReadTimeout异常,核心原因是同步阻塞调用异步方法导致FileStream状态异常。代码中用Wait()强制等待异步任务完成,会阻塞主线程,导致FileStream在等待过程中被错误触发超时检查;另外手动设置Content-Length也可能引发流长度不匹配的问题。

修复步骤与代码

关键修改点

  • 全程使用async/await替代同步阻塞的Wait(),避免流状态被干扰
  • 移除手动添加的Content-Length头,StreamContent会自动根据流长度生成正确的头信息
  • 规范HttpClient的使用(控制台程序建议复用单例,或者在using块内正确异步调用)
  • 简化异步获取Token的逻辑,去掉冗余的Task.Run包裹

修复后的完整代码

using System.Net.Http.Headers;
using Microsoft.Identity.Client;

class Program
{
    static async Task Main(string[] args)
    {
        // 替换为你的实际参数
        string appid = "你的AppId";
        string clientsecret = "你的ClientSecret";
        string aadid = "你的AAD租户ID";
        string url = "Dynamics 365的上传API地址";
        string nameCleared = "清理后的文件名";

        // 推荐复用HttpClient,避免频繁创建导致Socket资源耗尽
        using var httpClient = new HttpClient();

        using (var filestream = File.OpenRead(@"C:\test\test.pdf"))
        {
            var streamContent = new StreamContent(filestream);
            streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

            // 获取认证Token
            var _application = ConfidentialClientApplicationBuilder
                                   .Create(appid)
                                   .WithClientSecret(clientsecret)
                                   .WithAuthority(new Uri($"https://login.microsoftonline.com/{aadid}"))
                                   .Build();

            var authResult = await _application.AcquireTokenForClient(new[] { $"orgname.crm4.dynamics.com/.default" })
                                               .ExecuteAsync();

            // 构造上传请求并发送
            using (var req = new HttpRequestMessage(HttpMethod.Patch, url))
            {
                req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
                req.Content = streamContent;
                req.Content.Headers.Add("x-ms-file-name", $"{nameCleared}.pdf");

                using (var response = await httpClient.SendAsync(req))
                {
                    response.EnsureSuccessStatusCode();
                }
            }
        }
    }
}

额外说明

  1. 异步编程规范:控制台程序的Main方法标记为async Task后,可直接用await处理异步任务,彻底避免同步阻塞带来的线程状态问题。
  2. 流生命周期管理:FileStream被StreamContent使用时,只要保持using块的正确嵌套,流会在请求完成后自动释放,无需手动关闭。
  3. HttpClient复用:频繁创建HttpClient会导致系统Socket资源耗尽,推荐在程序生命周期内复用单个实例。

内容的提问来源于stack exchange,提问作者freudi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 15:01:10