none
FTP File Downloader RRS feed

  • Question

  • Hi Guys,

    I am in the process of creating an FTP file downloader and even though files download just fine, I can't get the download percentage working.

    I am having a lot of trouble calculating and displaying the download percentage to a label. I have tried countless examples from the web and nothing works for me. Not all examples can be wrong so I'm obviously doing something wrong. In particular, what happens when I click download is that the file downloads as per normal to its specified location but the percentage never changes. This also means that I can't get a progress bar to work.

    In addition to that the background worker doesn't seem to cancel when I call CancelAsync(). I have tried many examples and tutorials from websites, I've ruined the code and fixed it again and I still can't seem to solve these problems.

    Any ideas based on the existing code on how I can solve these two problems?

    Any feedback would be very much appreciated.

    EDIT -- UPDATED CODE

    using System.Windows.Forms;
    using System.Diagnostics;
    using System.Net;
    using System.Threading;
    using System;
    using System.ComponentModel;
    
    namespace FileDownloader
    {
        public partial class FileDownloaderForm : Form
        {
            //●	A progress bar with the state of the transfer
            //●	Transfer rate - OK
            //●	Estimated time left
            //●	Downloaded bytes - OK
    
            //TODO - Fix percentage
            //TODO - Fix progress bar
            //TODO - Fix estimated time left
    
            /// <summary>
            /// Global variables
            /// </summary>
            WebClient webClient;
            Stopwatch stopWatch = new Stopwatch();
    
            public FileDownloaderForm()
            {
                InitializeComponent();
                textUrl.Focus();
            }
    
            /// <summary>
            /// On-Form load
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void FileDownloaderForm_Load(object sender, EventArgs e)
            {
                webClient = new WebClient();
                webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(WebClient_DownloadProgressChanged);
                webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(WebClient_DownloadFileCompleted);
            }
    
            /// <summary>
            /// Add a users credentials and preference to a save path
            /// </summary>
            User user = new User { UserName = "User", Password = "Pass", SavePath = @"SavePath" };
    
    
            /// <summary>
            /// Download button on-click
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void DownloadButton_Click(object sender, EventArgs e)
            {
                if (!backgroundWorker.IsBusy)
                {
                    DownloadButton.Enabled = false;
                    backgroundWorker.RunWorkerAsync();
                }
            }
    
            /// <summary>
            /// What we want happening during the download. Update labels, count etc.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void WebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
            {
                Invoke(new MethodInvoker(delegate ()
                {
                    //These are the problem and the progress bar
                    double bytesIn = e.BytesReceived;
                    double totalBytes = e.TotalBytesToReceive;
                    bytesIn += bytesIn;
                    int totalSize = bytesIn / totalBytes * 100;
                    backgroundWorker.ReportProgress(totalSize + 1, totalSize);
    //Here we are ok
                    showTransferRate.Text = string.Format("{0} bytes/s", (e.BytesReceived / 1024d / stopWatch.Elapsed.TotalSeconds).ToString("0.00##"));//Works
                    showDownloadedBytes.Text = e.BytesReceived.ToString();//Works
                }));
            }
    
            /// <summary>
            /// Download completed. Close the doors
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void WebClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
            {
                stopWatch.Stop();
                ((WebClient)sender).Dispose();
                backgroundWorker.CancelAsync();
                MessageBox.Show("Download completed", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
    
    
            /// <summary>
            /// Background Worker executes the thread which connects to a server, gets a file, and saves it to a location
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
            {
                if (!backgroundWorker.CancellationPending)
                {
                    string url = textUrl.Text;
                    if (!string.IsNullOrEmpty(url))
                    {
                        webClient.Credentials = new NetworkCredential(user.UserName, user.Password);
    
                        Thread thread = new Thread(() => 
                        {
                            stopWatch.Start();
                            Uri uri = new Uri(url);
                            string fileName = System.IO.Path.GetFileName(uri.AbsolutePath);
                            webClient.DownloadFileAsync(uri, user.SavePath);
                        });
                        thread.Start();
                    }
                }
            }
        }
    }



     




    • Edited by NikosKapa Wednesday, February 7, 2018 1:35 PM Correction
    Tuesday, February 6, 2018 9:45 PM

All replies

  • Make sure that the minimum value of progress bar is zero and the maximum value is 100.

    Then adjust the ‘ReportProgres’ line:

       backgroundWorker.ReportProgress( (int)(fileStream.Length * 100 / totalBytes) );

    and insert the next line to ‘backgroundWorker_ProgressChanged’:

       progressBar1.Value = e.ProgressPercentage;

     

    I think that the if that checks the cancelation should be moved to while loop.

    Wednesday, February 7, 2018 8:40 AM
  • Hi NikosKapa,

    Thank you for posting here.

    For your question, please try the code below.

      protected override void OnLoad(EventArgs e)
            {
                base.OnLoad(e);
                backgroundWorker1.RunWorkerAsync();
            }
    
         
            string _userName = "xxxxx";
            string _password = "xxxxx";
            string _address = "localhost/";
            string _localPath = @"C:\Users\v-wezan\Desktop\88\";
            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                string fileName = "RasterEdge.DocImageSDK.zip";
    
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + this._address + "/" + fileName);
                request.Credentials = new NetworkCredential(this._userName, this._password);
                request.Method = WebRequestMethods.Ftp.GetFileSize;
                request.Proxy = null;
    
                long fileSize; // this is the key for ReportProgress
                using (WebResponse resp = request.GetResponse())
                    fileSize = resp.ContentLength;
    
                request = (FtpWebRequest)WebRequest.Create("ftp://" + this._address + "/" + fileName);
                request.Credentials = new NetworkCredential(this._userName, this._password);
                request.Method = WebRequestMethods.Ftp.DownloadFile;
                using (FtpWebResponse responseFileDownload = (FtpWebResponse)request.GetResponse())
                using (Stream responseStream = responseFileDownload.GetResponseStream())
                using (FileStream writeStream = new FileStream(this._localPath + fileName, FileMode.Create))
                {
    
                    int Length = 2048;
                    Byte[] buffer = new Byte[Length];
                    int bytesRead = responseStream.Read(buffer, 0, Length);
                    int bytes = 0;
    
                    while (bytesRead > 0)
                    {
                        writeStream.Write(buffer, 0, bytesRead);
                        bytesRead = responseStream.Read(buffer, 0, Length);
                        bytes += bytesRead;// don't forget to increment bytesRead !
                        int totalSize = (int)(fileSize) / 1000; // Kbytes
                        backgroundWorker1.ReportProgress((bytes / 1000) * 100 / totalSize + 1, totalSize);
                    }
                }
            }
    
            private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                progressBar1.Value = e.ProgressPercentage;
                this.label1.Text = e.ProgressPercentage.ToString() + "%";
            }

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, February 7, 2018 8:42 AM
    Moderator
  • Hello Wendy,

    Thank you very much for your time but unfortunately I've changed my code and it's a little bit different now. I've been going crazy on this. I thought I'd try WebClient out but I'm having the same problems. I did try implementing your solution in the new code but I'm obviously doing something wrong. 

    This is my code now.

    using System.Windows.Forms;
    using System.Diagnostics;
    using System.Net;
    using System.Threading;
    using System;
    using System.ComponentModel;
    
    namespace FileDownloader
    {
        public partial class FileDownloaderForm : Form
        {
            //●	A progress bar with the state of the transfer
            //●	Transfer rate - OK
            //●	Estimated time left
            //●	Downloaded bytes - OK
    
            //TODO - Fix percentage
            //TODO - Fix progress bar
            //TODO - Fix estimated time left
    
            /// <summary>
            /// Global variables
            /// </summary>
            WebClient webClient;
            Stopwatch stopWatch = new Stopwatch();
    
            public FileDownloaderForm()
            {
                InitializeComponent();
                textUrl.Focus();
            }
    
            /// <summary>
            /// On-Form load
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void FileDownloaderForm_Load(object sender, EventArgs e)
            {
                webClient = new WebClient();
                webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(WebClient_DownloadProgressChanged);
                webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(WebClient_DownloadFileCompleted);
            }
    
            /// <summary>
            /// Add a users credentials and preference to a save path
            /// </summary>
            User user = new User { UserName = "User", Password = "Pass", SavePath = @"SavePath" };
    
    
            /// <summary>
            /// Download button on-click
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void DownloadButton_Click(object sender, EventArgs e)
            {
                if (!backgroundWorker.IsBusy)
                {
                    DownloadButton.Enabled = false;
                    backgroundWorker.RunWorkerAsync();
                }
            }
    
            /// <summary>
            /// What we want happening during the download. Update labels, count etc.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void WebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
            {
                Invoke(new MethodInvoker(delegate ()
                {
                    //These are the problem and the progress bar
                    double bytesIn = e.BytesReceived;
                    double totalBytes = e.TotalBytesToReceive;
                    bytesIn += bytesIn;
                    int totalSize = bytesIn / totalBytes * 100;
                    backgroundWorker.ReportProgress(totalSize + 1, totalSize);
    //Here we are ok
                    showTransferRate.Text = string.Format("{0} bytes/s", (e.BytesReceived / 1024d / stopWatch.Elapsed.TotalSeconds).ToString("0.00##"));//Works
                    showDownloadedBytes.Text = e.BytesReceived.ToString();//Works
                }));
            }
    
            /// <summary>
            /// Download completed. Close the doors
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void WebClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
            {
                stopWatch.Stop();
                ((WebClient)sender).Dispose();
                backgroundWorker.CancelAsync();
                MessageBox.Show("Download completed", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
    
    
            /// <summary>
            /// Background Worker executes the thread which connects to a server, gets a file, and saves it to a location
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
            {
                if (!backgroundWorker.CancellationPending)
                {
                    string url = textUrl.Text;
                    if (!string.IsNullOrEmpty(url))
                    {
                        webClient.Credentials = new NetworkCredential(user.UserName, user.Password);
    
                        Thread thread = new Thread(() => 
                        {
                            stopWatch.Start();
                            Uri uri = new Uri(url);
                            string fileName = System.IO.Path.GetFileName(uri.AbsolutePath);
                            webClient.DownloadFileAsync(uri, user.SavePath);
                        });
                        thread.Start();
                    }
                }
            }
        }
    }

    Would it be possible to alter the code to suit this?

    Thank you very much and sorry for the hassle,

    Nikos

    Wednesday, February 7, 2018 1:24 PM
  • Updated the code. Thanks. 
    Wednesday, February 7, 2018 1:35 PM
  • Hi NikosKapa,

    Please try the code below.

     bool IsComlate;
            private void DownloadFileCompleted()
            {
                IsComlate = true;
            }    
            private void DownloadProgressChanged(int val)
            {
                progressBar1.Value = val;
                label1.Text = val.ToString() + "%";
                progressBar1.PerformStep();
            }
          
            private void DownloadFile(string url, string saveFile, Action<int> downloadProgressChanged, Action downloadFileCompleted)
            {
                WebClient client = new WebClient();
                client.Proxy = null;
                if (downloadProgressChanged != null)
                {
                    client.DownloadProgressChanged += delegate (object sender, DownloadProgressChangedEventArgs e)
                    {
                        this.Invoke(downloadProgressChanged, e.ProgressPercentage);
                    };
                }
                if (downloadFileCompleted != null)
                {
                    client.DownloadFileCompleted += delegate (object sender, AsyncCompletedEventArgs e)
                    {
                        this.Invoke(downloadFileCompleted);
                    };
                }
                client.DownloadFileAsync(new Uri(url), saveFile);
            }  
    
            private void button1_Click_1(object sender, EventArgs e)
            {
                DownloadFile("https://1drv.ms/u/s!AjN8-P8LNSQbwQabA7EFKshc3MEQ", @"test.mp3", DownloadProgressChanged, null);
            }

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, March 7, 2018 5:59 AM
    Moderator