0

i created a xamarin.forms application. in this app, the students must download the video lessons according to their grades and the subject in concern. i stored the .mp4 videos in a folder in a web api. the thing is that the video is taking a lot of time to be downloaded that the app crashes. here is my web api code for getting the video:

 public DataTable PostvideoFilesFromfolder([FromBody] uploadPdfModel user)
        {
            DataTable dt = new DataTable();
            dt.TableName = "videoDetails";

            DataTable dt2 = new DataTable();
            dt2.TableName = "videoDetails2";

            dt2.Columns.Add("pages", typeof(string));
            dt2.Columns.Add("videofile", typeof(byte[]));
            dt2.Columns.Add("videoFileName", typeof(string));
            SqlConnection conn = new SqlConnection(DBConnection);

            try
            {
                SqlCommand cmd = new SqlCommand("getvideoFilesdownload", conn);

                cmd.CommandType = CommandType.StoredProcedure;

                if (conn.State == System.Data.ConnectionState.Closed)
                {
                    conn.Open();
                }
              //   cmd.Parameters.Add("@id", SqlDbType.Text).Value = user.id;
                cmd.Parameters.Add("@grade", SqlDbType.Text).Value = user.grade;
                cmd.Parameters.Add("@section", SqlDbType.Text).Value = user.section;
                cmd.Parameters.Add("@subject", SqlDbType.Text).Value = user.subject;
                cmd.Parameters.Add("@lesson", SqlDbType.Int).Value = user.lesson;
                cmd.Parameters.Add("@pages", SqlDbType.Text).Value = user.pages;






                cmd.CommandTimeout = 300;
                SqlDataAdapter da = new SqlDataAdapter(cmd);

                da.Fill(dt);
              //  string name= dt.Rows[0]["videoFileName"].ToString();
              foreach(DataRow row in dt.Rows)
                {
                    string filePath = "videoFiles/"+user.subject+"/" + row["videoFileName"].ToString();
                    string fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, filePath);
                    byte[] fileBytes = File.ReadAllBytes(fullPath);
                    dt2.Rows.Add(row["pages"].ToString(), fileBytes, row["videoFileName"].ToString());
                }
             

            }
            finally
            {
                conn.Close();
            }


            return dt2;
        }

and here is the code in the app where i download the video and try to display it:

 async private void videoContent_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            videolst.IsVisible = false;
            // Image img = sender as Image;

            videoFileDetailspages selecteditem = videoContent.SelectedItem as videoFileDetailspages;

            //await DisplayAlert("l", "l", "k");
            int lessonNb = selecteditem.lesson;
            videoFileDetails lesson = new videoFileDetails();
            lesson = await App.Database.GetvideoAsync(grd, subj, lessonNb,selecteditem.pages);
            //await DisplayAlert("l", "l", "k");
            if (lesson == null)
            {
                popupLoadingView.IsVisible = true;
                activityIndicator.IsRunning = true;
                urlClass urldata = new urlClass();
                string uri = urldata.url + "/PostvideoFilesFromfolder";
                videodownload data = new videodownload();
                data.grade = grd;
                data.section = "";
                data.subject = subj;
                data.lesson = lessonNb;
                data.pages=selecteditem.pages;
                StringContent content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
                try
                {
                    HttpResponseMessage responsepost = await client.PostAsync(uri, content);

                    if (responsepost.IsSuccessStatusCode == true)
                    {
                        string outcome = await responsepost.Content.ReadAsStringAsync();
                        var result = JsonConvert.DeserializeObject<List<videodownload>>(outcome);

                        await App.Database.SavevideoAsync(new videoFileDetails
                        {
                            subject = subj,
                            grade = grd,
                            Name = result[0].videoFileName,
                            lesson = lessonNb


                        });

                        Stream writingStream = new MemoryStream(result[0].videofile);

                        string downloadpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), result[0].videoFileName);
                        File.WriteAllBytes(downloadpath, result[0].videofile);



                        // await DisplayAlert(";oijohjhj", "Please, Check Your Credentials!", "Cancel");
                        popupLoadingView.IsVisible = false;
                        activityIndicator.IsRunning = false;
                        var stack = this.Navigation.NavigationStack;
                        if (stack[stack.Count - 1].GetType() != typeof(videoDisplayPage))
                        {
                            await Navigation.PushAsync(new videoDisplayPage(downloadpath));
                        }





                    }


                    else
                    {
                        await DisplayAlert("Operation Failed", responsepost.IsSuccessStatusCode.ToString(), "Cancel");
                    }
                }
                catch (System.Net.WebException exp)
                {
                    await DisplayAlert("Connection Failed", "Please Check Your Internet Connection!", "Cancel");
                }
            }

            else
            {
                string pathopen = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), App.Database.GetvideoAsync(grd, subj, lessonNb,selecteditem.pages).Result.Name);

                var stack = this.Navigation.NavigationStack;
                if (stack[stack.Count - 1].GetType() != typeof(videoDisplayPage))
                {
                    await Navigation.PushAsync(new videoDisplayPage(pathopen));
                }
                //await DisplayAlert("s", "ll", "kk");
            }

        }

what should i do to make it faster or to make the app wait until the video is downloaded and not crash?

thanks in advance

i updated my web service code to this:

 public byte [] PostvideoFilesFromfolder([FromBody] uploadPdfModel user)
        {
            DataTable dt = new DataTable();
            dt.TableName = "videoDetails";

          

            byte[] videodata = { };

            SqlConnection conn = new SqlConnection(DBConnection);

            try
            {
                SqlCommand cmd = new SqlCommand("getvideoFilesdownload", conn);

                cmd.CommandType = CommandType.StoredProcedure;

                if (conn.State == System.Data.ConnectionState.Closed)
                {
                    conn.Open();
                }
             
                cmd.Parameters.Add("@grade", SqlDbType.Text).Value = user.grade;
                cmd.Parameters.Add("@section", SqlDbType.Text).Value = user.section;
                cmd.Parameters.Add("@subject", SqlDbType.Text).Value = user.subject;
                cmd.Parameters.Add("@lesson", SqlDbType.Int).Value = user.lesson;
                cmd.Parameters.Add("@pages", SqlDbType.Text).Value = user.pages;






                cmd.CommandTimeout = 300;
                SqlDataAdapter da = new SqlDataAdapter(cmd);

                da.Fill(dt);
              //  string name= dt.Rows[0]["videoFileName"].ToString();
              foreach(DataRow row in dt.Rows)
                {
                    string filePath = "videoFiles/"+user.subject+"/" + row["videoFileName"].ToString();
                    string fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, filePath);
                     videodata = File.ReadAllBytes(fullPath);
                  
                }
             

            }
            finally
            {
                conn.Close();
            }


            return videodata;
        }

but it is still taking a lot of time to download
rana hd
  • 355
  • 3
  • 18
  • don't embed the video in a json response. Create a separate endpoint that returns just the binary video data separate from the other data – Jason Apr 26 '23 at 13:12
  • would you please elaborate. do you mean i shouldn't return a datatable in the web service, just return a byte array or are you talking about the part corresponding to the xamarin.forms code? – rana hd Apr 26 '23 at 13:21
  • First, I wouldn't use a datatable for anything. Second, I'm saying the metadata should be returned in one request, and the actual binary video data in another. That's how I would do it. – Jason Apr 26 '23 at 13:26
  • You need to figure out exactly what part of this is slow. Is the file large? Do you have a slow connection? Is the code in the endpoint itself slow? Is the SQL query in your endpoint optimized? – Jason Apr 26 '23 at 13:40
  • the file size is 9 MB so i guess it is large right – rana hd Apr 26 '23 at 13:45
  • no, that is not particularly large – Jason Apr 26 '23 at 13:47
  • You can use the httpclient or webclient t download the vedio with the stream instead of json string. – Liyun Zhang - MSFT Jun 02 '23 at 10:27
  • @LiyunZhang-MSFT would you please tell me more about this – rana hd Jun 03 '23 at 18:43
  • You can refer to [this answer](https://stackoverflow.com/a/72851999/17455524). – Liyun Zhang - MSFT Jun 05 '23 at 10:03
  • i tried it. it still takes a lot of time :( – rana hd Jun 08 '23 at 14:35

0 Answers0