0
votes

Any Help or insight would be much appreciated.

What I have managed to obtain is that the issue is related to HTTPS as I am able to receive a 200 back when posting to an HTTP endpoint, similar to the following thread here

Currently having a difficult time trying to resolve the following issue:

I'm using the AndroidClientHandler HttpClient implementation as well as the NativeTLS 1.2+ for the SSL/TLS Implementation

When I record a Video on my app that is longer than 1 min, or larger than 20MB I receive the following error: "Cannot access a disposed object.\nObject name: 'System.Net.Sockets.NetworkStream'."

Here is the Method

    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;
    }

Below is the Stack Trace:

" at System.Net.WebConnectionStream.EndWrite (System.IAsyncResult r) [0x000b8] in <5a97d41d36694fb19855c17429527b10>:0 \n at System.IO.Stream+<>c.b__53_1 (System.IO.Stream 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--- End of stack trace from previous location where exception was thrown ---\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 \n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 \n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 \n at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 \n at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in :0 \n at System.Net.Http.MultipartContent+d__8.MoveNext () [0x0025d] in <996a681f30a44cd685a4da54e11956e2>:0 \n--- End of stack trace from previous location where exception was thrown ---\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 \n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 \n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 \n at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 \n at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in :0 \n at System.Net.Http.HttpClientHandler+d__64.MoveNext () [0x0036e] in <996a681f30a44cd685a4da54e11956e2>:0 \n--- End of stack trace from previous location where exception was thrown ---\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 \n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 \n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 \n at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 \n at 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 …

1
Can you curl the same size file to your web server? If so have you tried a different http-based client, like okhttp, in your program?SushiHangover
Also copying large content into a memory stream seems less optimal.Cheesebaron
I am surprised by the fact that he is not going OOM after converting a memory stream supposedly that big.FreakyAli
following other comments, what is obvious old low heap size android is running out of memory holding your large file and your object is disposed/cleaned from memory. think about a solution like snot loading whole file but splitting in memory chunks when sending.Nick Kovalsky
Thank you all for the comments, Ive been considering chunk upload and I believe it may be the best route. IKING

1 Answers

1
votes

I have resolved the issue by setting some flags in the Project Build Settings within Xamarin.Android.

Contrary to what the Docs suggest, setting the following configuration allows for me to POST the file to my server using HTTPS. While using the Native TLS 1.2+ crashes on uploads larger than 20MB...yes our server supports TLS 1.2

enter image description here