网络条件差时如何处理文件HttpClient.PostAsync文件上传?

Posted

技术标签:

【中文标题】网络条件差时如何处理文件HttpClient.PostAsync文件上传?【英文标题】:How to handle file HttpClient.PostAsync file upload under poor network conditions? 【发布时间】:2015-03-04 18:04:08 【问题描述】:

我正在开发一个以将多张照片上传到 Web api 为中心的移动应用程序。我正在使用 Xamarin.Forms 和 System.Net.Http.HttpClient 以及 Clumsy 来模拟糟糕的网络条件(滞后、丢包、无序数据包)。该应用程序最初是用 Titanium 编写的,对大多数用户来说运行良好,但一些移动网络较差的用户经常出现错误。展望未来,我们将移植到 Xamarin 并尝试适应连接性较差的用户。

using (var httpClient = CreateClient())
        
            httpClient.Timeout = TimeSpan.FromMinutes(5);
            using (var formData = new MultipartFormDataContent())
            
                // add required fields via formData.Add() ...

                var httpContent = new ByteArrayContent(imageData);
                formData.Add(httpContent, "file", Guid.NewGuid() + ".jpg");

                try
                
                    var response = await httpClient.PostAsync("fileupload", formData).ConfigureAwait(false);

                    if (response.IsSuccessStatusCode)
                    
                        responseObject = await ResponseMessageToResponseModel(response).ConfigureAwait(false);
                    
                
                catch (HttpRequestException ex)
                
                    Debug.WriteLine("HttpRequestException");
                
                catch (TaskCanceledException ex)
                
                    Debug.WriteLine("TaskCanceledException");
                
            
        

然而,我发现在正常条件下一切正常;当使用“滞后、丢弃、乱序”启用 Clumsy 并尝试上传时,PostAsync() 永远不会完成并最终因 TaskCanceledException 而超时。奇怪的是文件最终在服务器上。所以 POST 数据显然可以通过。

我猜测服务器响应中丢弃的数据包意味着 HttpClient 永远不会收到正确的响应并继续等待直到超时。

直截了当,我想知道是否有人对如何使这个过程尽可能防弹有任何想法。如果文件第一次通过,那么仅仅抓住超时并再次尝试就不会很好地工作。有什么想法吗?

此外,任何有关 HttpClient 如何处理丢弃/无序数据包的信息,以便我更好地了解正在发生的事情也会很棒。

【问题讨论】:

我做了一些额外的测试,发现了一些有趣的东西。启用 Clumsy(传入和传出)如果我保持启用状态,我会得到最初描述的情况(文件成功上传,但 PostAsync 超时并抛出 TaskCanceledException)。但是,如果我在几分钟后关闭 Clumsy,那么一切都会成功。这是否意味着来自 web api 服务器的响应会一遍又一遍地发送,直到收到确认? 【参考方案1】:

不久前我对 HttpClient 的一件事是对 POST 请求的特殊(读取不常见)处理。 发送 POST 请求时,它首先将标头(包括 ContentLenght 和特殊的 Expect: 100-continue 标头)发送到服务器,但没有正文。如果请求可以接受,则等待服务器响应状态码 100。之后,它开始发送身体。 此处的附加信息: MSDN Page for ServicePointManager.Expect100Continue MSDN blog post with some details

在我的情况下,问题是当请求大小太大而无法处理时,我正在与之交谈的后端服务(Play 框架)没有很好地处理协议的这一部分。它没有返回任何错误。并且请求只是超时了。所以禁用它 ServicePointManager.Expect100Continue = false; 在向该主机发送 任何 请求之前就为我解决了这个问题。至少现在它正在返回一些东西。

如果这没有帮助,我可以推荐的最好的方法是使用 wireshark 或类似的东西来查看电线上发生的事情。前提是它与您正在使用的这个 Clumsy 工具配合得很好。 (顺便谢谢你的链接。我自己也在找这样的东西)

【讨论】:

以上是关于网络条件差时如何处理文件HttpClient.PostAsync文件上传?的主要内容,如果未能解决你的问题,请参考以下文章

家庭网络有线电视IPTV网络电视的对比

飞驰学堂如何完成网络隔离条件下的文件跨网外发?

批处理 – Findstr 错误级别条件,引号? [复制]

在批处理文件中,如果满足一个条件而不是周围的 for 循环,如何突破嵌套的 if 语句?

Java IO流详解——缓冲流

在 Swift 中向用户显示网络错误消息