c# - HttpClient 收到服务器响应后停止推流失败

标签 c# .net dotnet-httpclient

我一直在为 .NET 4.5 中的 HttpClient 苦苦挣扎。通过分块传输将大量流式上传到 WebApi 端点时,当服务器已经使用非成功状态代码(未找到、身份验证、授权、验证错误等)响应中间请求时,它无法停止。

查看 ConnectStream 类中的调试器,它知道它从服务器收到了非成功状态。从服务器接收到的 HTTP 状态和数据被存储以备后用,从那一刻起它就假装从流中读取数据直到结束。从那一刻起,网络上什么也没有写,稍后通过 HttpResponseMessage 提供响应。这种无法解释的行为给我带来了很多问题,因为有问题的流可能非常大。无用的时间花在阅读流直到最后,而且向用户显示不正确的上传报告。我停止了网络服务器、远程机器,甚至禁用了本地网络接口(interface)。 HttpClient 不关心。它继续从提供的流中读取。

我尝试使用 HttpCompletionOption.ResponseHeadersReadStreamedContentPushStreamContent。相同的行为。我也尝试过使用 HttpWebRequest,但是这不允许同时写入输出流和读取传入流。有什么方法可以阻止客户端在收到服务器的响应后发送或假装发送流?为什么 HttpClient 会这样?

var httpClientHandler = new WebRequestHandler
    {
         AllowAutoRedirect = true,
         PreAuthenticate = false,
         CookieContainer = cookieContainer,
         UseCookies = true,
         CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore),                                        
         AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
    };
var httpClient = new HttpClient(_httpClientHandler)
    {
          BaseAddress = baseApiUrl,                                  
          Timeout = Timeout.InfiniteTimeSpan; 
    };
httpClient.DefaultRequestHeaders.TransferEncodingChunked = true;
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain", 0.8));
httpClient.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("UTF-8"));
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(appName, appVersion));

var requestContent = new StringContent(serializedRequest, Encoding.UTF8, "application/json");

// the monitored stream is an implementation of the stream that proxies the calls to a classic file stream
// here I monitor the calls made to Read(byte[] buffer, int offset, int count) method 
// tried with both CanSeek = false or true - the HttpClient reads the whole stream no matter what.
var streamedContent =  new StreamContent(monitoredStream);
streamedContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
    {
        FileName = "upload.bin",
        Size = monitoredStream.Length       
    };

var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, relativeUrl)
    {
        Content = new MultipartFormDataContent
            {
                requestContent,
                streamedContent    
            }
    };

// the Owin middleware could fail checking authentication, an authorization error could occur, 
//    or the WebApi controller could receive the first part of the multipart data and reject the request
// from the moment data was received from the server, mid-stream, I could safely unplug the network cable 
// socket erros are being ignored, actually the underlying socket is no longer used
// the response message contains the status code and data received during the transmission of the request at the end of this call
var httpResponseMessage = await _httpClient.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseHeadersRead, cancellationToken);

最佳答案

这是 HttpClient 中确认的限制。 Here is the Microsoft Connect case .也许它会在下一个版本中实现,但这不会影响投票。

关于c# - HttpClient 收到服务器响应后停止推流失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34309156/

相关文章:

c# - 线程 : Thread. CurrentThread.Name 和 Thread.CurrentThread.ManagedThereadId

java - 共同托管 Ruby on Rails 和另一个 Web 应用程序

c# - 将 "SetTitleTextAttributes"应用于后推按钮

c# - Ninject 注入(inject)接口(interface)的多重绑定(bind)

.net - 我可以使用 FtpWebRequest 类进行 SFTP 传输吗

asp.net-mvc - 为什么我的属性路由不起作用?

c# - 如何解决多个库中存在的 HttpClient

c# - 将处理程序添加到 ASP.NET Core 中的默认 http 客户端

c# - 使用延迟加载的 NHibernate ObjectProxy 转换

c# - StructureMap 有条件使用