Aswathy K R
Aswathy K R

Reputation: 177

Upload a long video to web API server from xamarin

I'am taking a 5 minute duration video and try to upload it into the API, but the response from the API is false and the video is not present in the Database. I uploaded small sized video to the API.

I found that the size of the video is high it takes more time to upload and the API is time out after some time. How to reduce the size of the video with out reducing it's content or upload a long duration video into the API with in few seconds.

Please help me..

Here is my code

private async void TakeVideo_Clicked(object sender, EventArgs e)
{
    if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakeVideoSupported)
    {
        await DisplayAlert("No Camera", ":( No camera avaialble.", "OK");
        return;
    }

    var _file = await CrossMedia.Current.TakeVideoAsync(new Plugin.Media.Abstractions.StoreVideoOptions
    {
        Name = "video.mp4",
        Directory = "Videos",
    });

    if (_file == null)
    {
        return;
    }
    else
    {
        _path = _file.Path;

        using (var _streamReader = new StreamReader(_file.GetStream()))
        {
            var _array = default(byte[]);                 

            using (MemoryStream _memoryStream = new MemoryStream())
            {
                _streamReader.BaseStream.CopyTo(_memoryStream);

                _array = _memoryStream.ToArray();                        

                if (await DisplayAlert(App._confirmation, "Do you want to save the video?", "Yes", "Cancel"))
                {
                    FileUploadAsync(_array, false);
                    activity_Indicator.IsVisible = true;
                    activity_Indicator.IsRunning = true;
                }
                else
                {
                    return;
                }
            }
        }
    }
}

public async void FileUploadAsync(byte[] fileUpload, bool IsImage)
    {
        APIResponse _response = await App.DataManager.UpdateFilesAsync(ID, fileUpload, IsImage);

        if (_response != null)
        {
            activity_Indicator.IsRunning = false;

            if (IsImage)
            {
                DependencyService.Get<IAlertPlayer>().AlertMessege("Image upload successfully");
            }
            else
            {
                DependencyService.Get<IAlertPlayer>().AlertMessege("Video upload successfully");
            }
        }
        else
        {
            DisplayAlertMessage();
        }
    }      

  public async Task<APIResponse>UpdateFilesAsync(int id,byte[] file,bool IsImage)
    {
        Url _url = new Url(BaseURL).AppendPathSegment("sample/UploadFiles");

        _url.QueryParams["ID"] = id;

        return await Service.POSTFILE<APIResponse>(_url, file,IsImage);
    }

Here is my POST method

public async Task<T> POSTFILE<T>(Url url, byte[] uploadFile, bool IsImage)
    {
        try
        {
            using (MultipartFormDataContent content = new MultipartFormDataContent())
            {
                ByteArrayContent filecontent = new ByteArrayContent(uploadFile);

                if (IsImage)
                {
                    filecontent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
                    {
                        FileName = Guid.NewGuid().ToString() + ".png"
                    };
                }
                else
                {
                    filecontent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
                    {
                        FileName = Guid.NewGuid().ToString() + ".mp4"
                    };
                }

                content.Add(filecontent);

                using (HttpResponseMessage response = await Client.PostAsync(url, content))
                {
                    string result = await response.Content.ReadAsStringAsync();
                    return JsonConvert.DeserializeObject<T>(result);
                }
            }
        }
        catch (Exception ex)
        {

        }

        return default(T);
    }
}

Upvotes: 2

Views: 3328

Answers (2)

KING
KING

Reputation: 980

So here is how i use video compression on Xamarin.iOS. You can make this into a service and then implement the proper compression logic based on the platform. Lastly if you are using IIS make sure you increase your video upload limit

        var asset = AVAsset.FromUrl(NSUrl.FromFilename(path));
        AVAssetExportSession exportSession = new AVAssetExportSession(asset, AVAssetExportSessionPreset.HighestQuality);

        exportSession.OutputUrl = NSUrl.FromFilename(pathService.GetCompressedPath());
        exportSession.OutputFileType = AVFileType.Mpeg4;
        exportSession.ShouldOptimizeForNetworkUse = true;

        await exportSession.ExportTaskAsync(); //This can cause an error so check the status

        Stream exportStream = File.OpenRead(path);

        return exportStream;

Android Implementation

        //create File from string.
        var file = new Java.IO.File(path);
        var outputFile = new Java.IO.File(pathService.GetCompressedPath());

        await Transcoder.For720pFormat().ConvertAsync(file, outputFile, null);

        Stream exportStream = File.OpenRead(outputFile.Path);

        System.Diagnostics.Debug.WriteLine("Stream read from file");

        return exportStream;

Upvotes: 2

Martin Zikmund
Martin Zikmund

Reputation: 39082

Unfortunately, there are no cross-platform solutions for video compression, so you would have to implement this compression in a platform-specific manner. Each platform should have such solution available if you search for those.

Alternatively, you could tweak the HttpClient.Timeout to a larger value (default is 100 seconds) so that the upload does not time out if the file is large. Of course the value depends on the requirements you have. You can even set it to be virtually infinite (TimeSpan.MaxValue), but then you have the risk of creating requests which never end and you would have to add some kind of manual cancellation using CancellationTokenSource.

Upvotes: 0

Related Questions