简体   繁体   English

如何在糟糕的网络条件下处理文件HttpClient.PostAsync文件上传?

[英]How to handle file HttpClient.PostAsync file upload under poor network conditions?

I'm working on developing a mobile app that is centered around uploading multiple photos to a web api. 我正在开发一个以将多张照片上传到网络API为中心的移动应用。 I'm using Xamarin.Forms and System.Net.Http.HttpClient, and Clumsy to simulate poor network conditions (lag, dropped packets, out-of-order packets). 我正在使用Xamarin.Forms和System.Net.Http.HttpClient,以及Clumsy来模拟糟糕的网络状况(滞后,丢包,无序数据包)。 The app was originally written with Titanium, and worked fine for most users, but some users on poor mobile networks were getting frequent errors. 该应用程序最初是用Titanium编写的,并且对大多数用户来说都很好,但是一些移动网络不佳的用户却经常出错。 Going forward we are porting to Xamarin and trying to accommodate users with poor connectivity. 展望未来,我们正在移植到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");
                }
            }
        }

What I'm finding is that everything works as expected under normal conditions, however; 我发现的是,一切都在正常条件下按预期工作; when enabling Clumsy with "lag, drop, out-of-order" and attempting the upload the PostAsync() never completes and eventually times out with TaskCanceledException. 当使用“滞后,丢弃,无序”启用Clumsy并尝试上载时,PostAsync()永远不会完成,并最终超时与TaskCanceledException。 The odd thing is that the file ends up on the server.. so the POST data apparently made it through okay. 奇怪的是文件最终在服务器上..所以POST数据显然已经通过了。

I'm guessing that packets dropped in the response from the server means the HttpClient never receives a proper response and continues to wait for one until it times out. 我猜测从服务器响应中丢弃的数据包意味着HttpClient从未收到正确的响应,并继续等待一个直到它超时。

To get to the point, I'm wondering if anyone has any ideas on how to make this process as bullet-proof as possible. 为了达到这一点,我想知道是否有人对如何使这个过程尽可能防弹有任何想法。 Just catching the timeout and trying again doesn't work very well if the file made it through the first time. 如果文件第一次完成,只是捕获超时并再次尝试不能很好地工作。 Any thoughts? 有什么想法吗?

Also, any info on how HttpClient handles dropped/out-of-order packets so I can better understand what's happening would be great as well. 此外,有关HttpClient如何处理丢弃/无序数据包的任何信息,以便我可以更好地了解正在发生的事情也会很棒。

One thing with HttpClient I banged my head at a while ago was special(read uncommon) handling of POST requests. HttpClient的一件事我不久前撞了我的头是特殊的(读取不常见)处理POST请求。 When sending POST request it first sends the headers (including ContentLenght and special Expect: 100-continue header) to the server but without the body. 发送POST请求时,它首先将标题(包括ContentLenght和特殊的Expect: 100-continue标题)发送到服务器但没有正文。 And waits for server to respond with status code 100 if request is acceptable. 如果请求可接受,则等待服务器以状态码100响应。 After that it starts sending the body. 之后它开始发送身体。 Additional info here: MSDN Page for ServicePointManager.Expect100Continue MSDN blog post with some details 其他信息: ServicePointManager.Expect100Continue MSDN博客文章的 MSDN页面, 其中包含一些详细信息

In my case the problem was that this part of the protocol wasn't handled particulary well by the backend service (Play framework) I was talking to when request size was too large for it to handle. 在我的情况下,问题是当请求大小太大而无法处理时,后端服务(Play框架)没有特别处理协议的这一部分。 It was not returning any error. 它没有返回任何错误。 And request simply timed out. 请求只是超时。 So disabling it with ServicePointManager.Expect100Continue = false; 因此,使用ServicePointManager.Expect100Continue = false;禁用它ServicePointManager.Expect100Continue = false; well ahead of sending any request to this host solved the problem for me. 在向该主机发送任何请求之前,我已经解决了这个问题。 At least now it was returning something. 至少现在它正在回归。

If that doesn't help than the best thing I can recommend is looking with wireshark or something similar at what is going on on the wire. 如果这没有帮助,那么我建议的最好的事情就是看看wirehark或类似的东西在电线上发生的事情。 Provided it plays nice with this Clumsy tool you're using. 如果你使用这个Clumsy工具很好玩。 (Thanks for the link by the way. Was looking for something like this myself) (顺便说一句,感谢你的链接。我自己也在寻找这样的东西)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM