【发布时间】:2018-08-15 20:57:11
【问题描述】:
任何帮助或见解将不胜感激。
我设法获得的是该问题与 HTTPS 有关,因为我能够在发布到 HTTP 端点时收到 200 回复,类似于以下线程 here
目前很难解决以下问题:
我正在使用 AndroidClientHandler HttpClient 实现以及用于 SSL/TLS 实现的 NativeTLS 1.2+
当我在我的应用上录制超过 1 分钟或大于 20MB 的视频时,我收到以下错误: "无法访问已处置的对象。\n对象名称: 'System.Net.Sockets.NetworkStream'。”
方法如下
public async Task<HttpResponseMessage> UploadVideo(string endPoint)
{
HttpResponseMessage responseMessage = null;
try
{
//Stopwatch stopWatch = new Stopwatch();
IList<KeyValuePair<string, string>> formFields = new List<KeyValuePair<string, string>>();
messageHandlerService = Mvx.Resolve<IMessageHandlerService>();
//Declare a scope whereby you can use resources and once you leave the scope the resources are disposed of.
using (StreamReader reader = pathService.GetStreamReaderByPlatform())
{
client = await MyHttpClient.GetClientAsync();
client.Timeout = TimeSpan.FromSeconds(500);
var bytes = default(byte[]);
using (var memstream = new MemoryStream())
{
reader.BaseStream.CopyTo(memstream);
bytes = memstream.ToArray();
using (var content = new MultipartFormDataContent())
{
var fileContent = new ByteArrayContent(bytes);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = ".mp4",
};
content.Add(fileContent);
content.Add(EncodeFields(formFields));
await Policy.Handle<TimeoutException>()
.Or<HttpRequestException>()
.Or<IOException>()
.OrResult<HttpResponseMessage>(r => httpStatusCodesToRetry.Contains(r.StatusCode))
.WaitAndRetryAsync
(retryCount: 3,
sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (ex, time) =>
{
Debug.WriteLine($"Something went wrong: {ex.Exception.Message}, retrying...");
}).ExecuteAsync(async () =>
{
Debug.WriteLine($"Trying to fetch remote data...");
responseMessage = await client.PostAsync(endPoint, content);
return responseMessage;
});
}
}
}
}
catch (WebException webx)
{
if (responseMessage == null)
{
responseMessage = new HttpResponseMessage();
}
responseMessage.StatusCode = HttpStatusCode.InternalServerError;
responseMessage.ReasonPhrase = string.Format("RestHttpClient.SendRequest failed: {0}", webx);
}
catch (Exception ex)
{
if (responseMessage == null)
{
responseMessage = new HttpResponseMessage();
}
responseMessage.StatusCode = HttpStatusCode.InternalServerError;
responseMessage.ReasonPhrase = string.Format("RestHttpClient.SendRequest failed: {0}", ex);
}
return responseMessage;
}
下面是堆栈跟踪:
" 在 System.Net.WebConnectionStream.EndWrite (System.IAsyncResult r) [0x000b8] in :0 \n 在 System.IO.Stream+c.b__53_1 (System.IO.Stream 流,System. IAsyncResult asyncResult) [0x00000] in :0 \n at (wrapper delegate-invoke) System.Func3[System.IO.Stream,System.IAsyncResult,System.Threading.Tasks.VoidTaskResult].invoke_TResult_T1_T2(System.IO.Stream,System.IAsyncResult)\n at System.Threading.Tasks.TaskFactory1+FromAsyncTrimPromise1[TResult,TInstance].Complete (TInstance thisRef, System.Func3[T1,T2,TResult] endMethod, System.IAsyncResult asyncResult, System.Boolean requiresSynchronization) [0x00000] in :0 \n--- 从先前引发异常的位置结束堆栈跟踪 ---\n 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 \n 在 System. Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task 任务) [0x0003e] in :0 \n System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task 任务) [0x00028] 在: 0 \n 在 System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task 任务) [0x00008] in :0 \n 在 System.Runti me.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in :0 \n 在 System.Net.Http.MultipartContent+d__8.MoveNext () [0x0025d] in :0 \n--- 堆栈结束从先前引发异常的位置跟踪 ---\n 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 \n 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.任务任务)[0x0003e] in :0 \n System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task 任务)[0x00028] in :0 \n System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd ( System.Threading.Tasks.Task task) [0x00008] in :0 \n System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in :0 \n System.Net.Http.HttpClientHandler+d__64。 MoveNext () [0x0036e] in :0 \n--- 堆栈跟踪从 pre抛出异常的位置 ---\n 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 \n 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task 任务) [0x0003e] in :0 \n System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task 任务) [0x00028] in :0 \n System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System. Threading.Tasks.Task 任务)[0x00008] in :0 \n 在 System.Runtime.CompilerServices.ConfiguredTaskAwaitable1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in <f32579baafc1404fa37ba3ec1abdc0bd>:0 \n at System.Net.Http.HttpClient+<SendAsyncWorker>d__49.MoveNext () [0x000ca] in <996a681f30a44cd685a4da54e11956e2>:0 \n--- End of stack trace from previous location where exception was thrown ---\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <f32579baafc1404fa37ba3ec1abdc0bd>:0 \n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <f32579baafc1404fa37ba3ec1abdc0bd>:0 \n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <f32579baafc1404fa37ba3ec1abdc0bd>:0 \n at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <f32579baafc1404fa37ba3ec1abdc0bd>:0 \n at System.Runtime.CompilerServices.TaskAwaiter1
…
【问题讨论】:
-
你能
curl把同样大小的文件放到你的网络服务器上吗?如果是这样,您是否在程序中尝试过其他基于 http 的客户端,例如 okhttp? -
将大量内容复制到内存流中似乎不太理想。
-
我很惊讶他在转换了这么大的内存流后并没有出现 OOM。
-
继其他 cmets 之后,很明显旧的低堆大小 android 内存不足,无法保存您的大文件,并且您的对象已从内存中释放/清除。考虑一个解决方案,例如 snot 加载整个文件但在发送时拆分内存块。
-
谢谢大家的cmets,我一直在考虑分块上传,我相信这可能是最好的路线。我
标签: android xamarin xamarin.android httpclient