Xamarin.Forms iOS集成Airwatch AppTunnel大文件上传网络连接丢失问题
我开发了一个基于Xamarin.Forms的移动应用,配套内部Web应用提供API接口供移动端调用。由于Web应用是内部系统,需通过隧道访问API,按客户要求在Xamarin.Forms iOS项目中集成了Airwatch SDK。根据Airwatch SDK AppTunnel文档要求,所有HttpClient请求均使用ModernHttpClient,目前已能通过AppTunnel正常访问内部API。
应用中有一个Multipart/Form-Data类型的文件上传POST接口,适配ModernHttpClient后小文件上传正常,但大文件上传时出现以下错误:
System.AggregateException: 发生一个或多个错误。(网络连接已丢失。) ---> System.Net.WebException: 网络连接已丢失。 ---> Foundation.NSErrorException: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=54, NSUnderlyingError=0x28370d980 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={_kCFStreamErrorCodeKey=54, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask .<1>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=https://base-url.com/api/v2/filesystem/upload, NSErrorFailingURLKey=https://base-url.com.com/api/v2/filesystem/upload, _kCFStreamErrorDomainKey=1}
--- End of inner exception stack trace ---
at ModernHttpClient.NativeMessageHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x1088d8130 + 0x01143> in <67401bece23c4316a0cb1acd7b396157#0821ad7e7f240e13aa5b8f0971c62be4>:0
at System.Net.Http.HttpClient.FinishSendAsyncBuffered (System.Threading.Tasks.Task1[TResult] sendTask, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationTokenSource cts, System.Boolean disposeCts) <0x1073d7a80 + 0x005f4> in <992c809de76342e0b46dc1b912da2d7b#0821ad7e7f240e13aa5b8f0971c62be4>:0 --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) <0x10490f1a0 + 0x00048> in <aae03b95719e488f8a163bae4d2b5dcb#0821ad7e7f240e13aa5b8f0971c62be4>:0 at System.Threading.Tasks.Task1[TResult].GetResultCore (System.Boolean waitCompletionNotification) <0x10490a080 + 0x00097> in <aae03b95719e488f8a163bae4d2b5dcb#0821ad7e7f240e13aa5b8f0971c62be4>:0
at System.Threading.Tasks.Task1[TResult].get_Result () <0x104909fe0 + 0x00067> in <aae03b95719e488f8a163bae4d2b5dcb#0821ad7e7f240e13aa5b8f0971c62be4>:0 at AppSDK.V2.Service.Uploader.SendStreamToServer (System.String fileName, System.IO.Stream stream, System.Collections.Specialized.NameValueCollection nvc) <0x107cd73b0 + 0x00633> in <d8bc2b7aa0fc423f94af434e3edd0df7#0821ad7e7f240e13aa5b8f0971c62be4>:0 ---> (Inner Exception #0) System.Net.WebException: 网络连接已丢失。 ---> Foundation.NSErrorException: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=54, NSUnderlyingError=0x28370d980 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={_kCFStreamErrorCodeKey=54, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <F5B801BE-A8A1-4EBC-89D2-EA1D79B4C72B>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask <F5B801BE-A8A1-4EBC-89D2-EA1D79B4C72B>.<1>" ), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=https://base-url.com.com/api/v2/filesystem/upload, NSErrorFailingURLKey=https://base-url.com.com/api/v2/filesystem/upload, _kCFStreamErrorDomainKey=1} --- End of inner exception stack trace --- at ModernHttpClient.NativeMessageHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x1088d8130 + 0x01143> in <67401bece23c4316a0cb1acd7b396157#0821ad7e7f240e13aa5b8f0971c62be4>:0 at System.Net.Http.HttpClient.FinishSendAsyncBuffered (System.Threading.Tasks.Task1[TResult] sendTask, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationTokenSource cts, System.Boolean disposeCts) <0x1073d7a80 + 0x005f4> in <992c809de76342e0b46dc1b912da2d7b#0821ad7e7f240e13aa5b8f0971c62be4>:0 <---
已尝试的解决方法(均无效)
- 将大文件分块上传(例如把850MB文件分成500KB块,但上传60-70MB后仍报错)
- 增加HttpClient超时时间:
_client.Timeout = TimeSpan.FromMinutes(20); - 增加ModernHttpClient的超时时间:
NativeMessageHandler handler = new NativeMessageHandler() { Timeout = TimeSpan.FromMinutes(20) }; HttpClient _client = new HttpClient(handler); - 为HTTP请求添加
Connection: Close头,尝试三种写法:httpClient.DefaultRequestHeaders.Add("Connection", "Close");httpClient.DefaultRequestHeaders.ConnectionClose = true;httpClient.DefaultRequestHeaders.ConnectionClose = false; - 为HTTP请求添加
Connection: Keep-Alive头并设置超时:httpClient.DefaultRequestHeaders.Add("Connection", "Keep-Alive"); httpClient.DefaultRequestHeaders.Add("Keep-Alive", "180000"); - 分别使用ModernHttpClient和modernhttpclient-updated两个版本测试上述所有方法
看到相关Issue提到可能是服务器端问题,但不清楚需要调整哪些设置。请问该如何解决大文件上传时出现的网络连接丢失问题?
内容的提问来源于stack exchange,提问作者Pelin Konaray

