FtpWebRequest FTP скачать с ProgressBar

Мой код работает, но ProgressBar сразу переместится на 100% и загрузка продолжится. Когда он закончится, приходит MessageBox для получения информации.

Я уже изменил размер буфера, но это не имеет значения.

Что я здесь не так делаю?

Вот мой код:

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 = " "; });      
}

3 ответа

Тривиальный пример загрузки через FTP FtpWebRequest с индикатором выполнения WinForms:

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:\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);
    }
}

введите описание изображения здесь

Код загрузки ядра основан на:
Загрузить и загрузить двоичный файл на / с FTP-сервера в C#/.NET


Чтобы объяснить, почему ваш код не работает:

  • Вы используете размер целевого файла для расчета: fileStream.Length - это всегда будет равно totalReadBytesCount, следовательно progress всегда будет 100.
  • Вы, вероятно, хотели использовать ftpStream.Length, но это не может быть прочитано.
  • В основном с протоколом FTP, вы не знаете размер загружаемого файла. Если вам нужно это знать, вы должны явно запросить его перед загрузкой. Здесь я использую WebRequestMethods.Ftp.GetFileSize для этого.

Теперь у меня есть решение, которое работает для меня.

Идея получить первый размер файла была отличной. Но когда я впервые делаю запрос для проверки размера файла, Ftp-сервер выдает ошибку. Как эта ошибка FtpWebRequest: 550 Размер не допускается в режиме ASCII

Теперь сначала я загружаю фиктивный файл, чтобы открыть соединение. См. Ниже

Спасибо всем за поддержку.

Великое Сообщество. Благодарю.

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 = " "; });


        }

Не зная точно, что ваш код в ProgressChanged Eventhandler делает, я думаю, что вы непреднамеренно поставили скобки в свой расчет прогресса после * 100,

Вы можете попробовать это:

var progress = (int)((float)totalReadBytesCount / (float)fileStream.Length) * 100;
Другие вопросы по тегам