FtpWebRequest FTP download with ProgressBar
Asked Answered
C

3

3

My code works, but the ProgressBar jumps directly to 100% and the download will go on. When its finished then comes a messageBox to take a Info.

I have already changed the buffer size, but it doesn't matter.

What am I doing wrong here?

Here is my Code:

void workerDOWN_DoWork(object sender, DoWorkEventArgs e)
{
    string fileFullPath = e.Argument as String;
    string fileName = Path.GetFileName(fileFullPath);
    string fileExtension = Path.GetExtension(fileName);

    label4.Invoke((MethodInvoker)delegate { label4.Text = "Downloading File.."; });

    string ftpServerIP = "XXX";
    string ftpUserName = "XXX";
    string ftpPassword = "XXX";

    try
    {
        //Datei vom FTP Server downloaden
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + ftpServerIP + "/" + fileName);
        request.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
        request.Method = WebRequestMethods.Ftp.DownloadFile;
        using (Stream ftpStream = request.GetResponse().GetResponseStream())
        using (Stream fileStream = File.Create(fileFullPath))
        {
            var buffer = new byte[32 * 1024];
            int totalReadBytesCount = 0;
            int readBytesCount;
            while ((readBytesCount = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                fileStream.Write(buffer, 0, readBytesCount);
                totalReadBytesCount += readBytesCount;
                var progress = (int)((float)totalReadBytesCount / (float)fileStream.Length * 100);
                workerDOWN.ReportProgress((int)progress);
                label3.Invoke((MethodInvoker)delegate { label3.Text = progress + " %"; });
            }
        }
    }
    catch (WebException ex)
    {
        FtpWebResponse response = (FtpWebResponse)ex.Response;

        if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
        {
            MessageBox.Show("Datei nicht gefunden!", "Error");
        }
    }
    e.Result = fileFullPath;
}


void workerDOWN_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
     string fileFullPath = e.Result as String;
     string fileName = Path.GetFileName(fileFullPath);

     MessageBox.Show("Download erfolgreich!","Information");

     progressBar1.Value = 0;
     label3.Invoke((MethodInvoker)delegate { label3.Text = " "; });
     label4.Invoke((MethodInvoker)delegate { label4.Text = " "; });      
}
Circumcision answered 23/7, 2017 at 19:46 Comment(0)
K
4

Trivial example of FTP download using FtpWebRequest with WinForms progress bar:

private void button1_Click(object sender, EventArgs e)
{
    // Run Download on background thread
    Task.Run(() => Download());
}

private void Download()
{
    try
    {
        const string url = "ftp://ftp.example.com/remote/path/file.zip";
        var credentials = new NetworkCredential("username", "password");

        // Query size of the file to be downloaded
        WebRequest sizeRequest = WebRequest.Create(url);
        sizeRequest.Credentials = credentials;
        sizeRequest.Method = WebRequestMethods.Ftp.GetFileSize;
        int size = (int)sizeRequest.GetResponse().ContentLength;

        progressBar1.Invoke(
            (MethodInvoker)(() => progressBar1.Maximum = size));
        
        // Download the file
        WebRequest request = WebRequest.Create(url);
        request.Credentials = credentials;
        request.Method = WebRequestMethods.Ftp.DownloadFile;

        using (Stream ftpStream = request.GetResponse().GetResponseStream())
        using (Stream fileStream = File.Create(@"C:\local\path\file.zip"))
        {
            byte[] buffer = new byte[10240];
            int read;
            while ((read = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                fileStream.Write(buffer, 0, read);
                int position = (int)fileStream.Position;
                progressBar1.Invoke(
                    (MethodInvoker)(() => progressBar1.Value = position));
            }
        }
    }
    catch (Exception e)
    {
        MessageBox.Show(e.Message);
    }
}

enter image description here

The core download code is based on:
Upload and download a file to/from FTP server in C#/.NET


To explain why your code does not work:

  • You are using size of the target file for the calculation: fileStream.Length – It will always be equal to totalReadBytesCount, hence the progress will always be 100.
  • You probably meant to use ftpStream.Length, but that cannot be read.
  • Basically with FTP protocol, you do not know size of the file you are downloading. If you need to know it, you have to query it explicitly before the download. Here I use the WebRequestMethods.Ftp.GetFileSize for that.
Kilroy answered 23/7, 2017 at 20:15 Comment(0)
C
1

i have now a solution thats work for me.

The Idea to get first the File Size was great. But when i first makes an query to check the File Size, the Ftp Server throws a Error. Like this FtpWebRequest error: 550 Size not allowed in ASCII mode

Now first i download a dummy file to open the Connection.. See below

Thanks to all for the Support.

Great Community. Thanks.

void workerDOWN_DoWork(object sender, DoWorkEventArgs e)
        {
            string fileFullPath = e.Argument as String;
            string fileName = Path.GetFileName(fileFullPath);
            string fileExtension = Path.GetExtension(fileName);

            label4.Invoke((MethodInvoker)delegate { label4.Text = "Downloading File.."; });

            //FTP Download und Delete
            string ftpServerIP = "XXX";
            string ftpUserName = "XXXX";
            string ftpPassword = "XXXXX";

            try
            {
                // dummy download ftp connection for ftp server bug
                FtpWebRequest DummyRequest = (FtpWebRequest)WebRequest.Create(("ftp://" + ftpServerIP + "/anyfile"));
                DummyRequest.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
                DummyRequest.Method = WebRequestMethods.Ftp.DownloadFile;
                using (Stream ftpStream = DummyRequest.GetResponse().GetResponseStream())
                using (Stream fileStream = File.Create(Path.GetDirectoryName(Application.ExecutablePath) + "\\anyfile"))
                {
                    ftpStream.CopyTo(fileStream);
                }
                //delete downloaded test file
                File.Delete(Path.GetDirectoryName(Application.ExecutablePath) + "\\anyfile");

                // Query size of the file to be downloaded
                FtpWebRequest sizeRequest = (FtpWebRequest)WebRequest.Create("ftp://" + ftpServerIP + "/" + fileName);
                sizeRequest.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
                sizeRequest.Method = WebRequestMethods.Ftp.GetFileSize;
                var fileSize = sizeRequest.GetResponse().ContentLength;

                //file download
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + ftpServerIP + "/" + fileName);
                request.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
                request.Method = WebRequestMethods.Ftp.DownloadFile;
                using (Stream ftpStream = request.GetResponse().GetResponseStream())
                using (Stream fileStream = File.Create(fileFullPath))
                {
                    var buffer = new byte[32 * 1024];
                    int totalReadBytesCount = 0;
                    int readBytesCount;
                    while ((readBytesCount = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        fileStream.Write(buffer, 0, readBytesCount);
                        totalReadBytesCount += readBytesCount;
                        var progress = (int)((float)totalReadBytesCount / (float)fileSize * 100);
                        workerDOWN.ReportProgress((int)progress);
                        label3.Invoke((MethodInvoker)delegate { label3.Text = progress + " %"; });
                    }
                }

                // delete file on ftp server
                FtpWebRequest Delrequest = (FtpWebRequest)WebRequest.Create("ftp://" + ftpServerIP + "/" + fileName);
                Delrequest.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
                Delrequest.Method = WebRequestMethods.Ftp.DeleteFile;
                FtpWebResponse Delresponse = (FtpWebResponse)Delrequest.GetResponse();
                Delresponse.Close();

                // message file deleted
                richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("System: " + fileName + " wurde auf dem Server gelöscht." + Environment.NewLine); });

            }
            catch (WebException ex)
            {
                FtpWebResponse response = (FtpWebResponse)ex.Response;

                if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
                {

                    MessageBox.Show("Datei nicht gefunden!", "Error");
                } 
            }

            e.Result = fileFullPath;

        }


        void workerDOWN_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }

        void workerDOWN_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
             string fileFullPath = e.Result as String;
             string fileName = Path.GetFileName(fileFullPath);

             MessageBox.Show("Download erfolgreich!","Information");

             progressBar1.Value = 0;
             label3.Invoke((MethodInvoker)delegate { label3.Text = " "; });
             label4.Invoke((MethodInvoker)delegate { label4.Text = " "; });


        }
Circumcision answered 24/7, 2017 at 15:3 Comment(0)
C
0

Without knowing exactly what your code in the ProgressChanged eventhandler does, I think that you unintentionally put the brackets in your progress calculation after * 100.

You could try this:

var progress = (int)((float)totalReadBytesCount / (float)fileStream.Length) * 100;
Cryptoclastic answered 23/7, 2017 at 20:0 Comment(1)
I was assuming that that's where you update the progress bar you mentioned. (see: msdn.microsoft.com/en-us/library/…) -- ReportProgress raises that event.Cryptoclastic

© 2022 - 2024 — McMap. All rights reserved.