Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
503 views
in Technique[技术] by (71.8m points)

c# - FtpWebRequest FTP download with ProgressBar

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 = " "; });      
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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";
        NetworkCredential 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:localpathfile.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 binary 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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...