Download FTP FtpWebRequest con ProgressBar

Il mio codice funziona, ma ProgressBar salta direttamente al 100% e il download continuerà. Quando è finito, arriva un messageBox per prendere un’informazione.

Ho già cambiato la dimensione del buffer, ma non importa.

Cosa sto facendo di sbagliato qui?

Ecco il mio codice:

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

Trivial esempio di download FTP usando FtpWebRequest con la barra di avanzamento di 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); } } 

inserisci la descrizione dell'immagine qui

Il codice di download principale si basa su:
Carica e scarica un file binario da / verso il server FTP in C # /. NET


Per spiegare perché il tuo codice non funziona:

  • Stai utilizzando la dimensione del file di destinazione per il calcolo: fileStream.Length : sarà sempre uguale a totalReadBytesCount , quindi il progress sarà sempre 100.
  • Probabilmente hai pensato di usare ftpStream.Length , ma questo non può essere letto.
  • Fondamentalmente con il protocollo FTP, non si conoscono le dimensioni del file che si sta scaricando. Se hai bisogno di saperlo, devi interrogarlo in modo esplicito prima del download. Qui utilizzo WebRequestMethods.Ftp.GetFileSize per questo.

Senza sapere esattamente che cosa fa il codice nel gestore di eventi ProgressChanged , penso che tu abbia involontariamente messo le parentesi nel tuo calcolo progressivo dopo * 100 .

Potresti provare questo:

 var progress = (int)((float)totalReadBytesCount / (float)fileStream.Length) * 100; 

ora ho una soluzione che funziona per me.

L’idea di ottenere prima la dimensione del file è stata grande. Ma quando prima faccio una query per verificare la dimensione del file, il server Ftp genera un errore. Come questo errore FtpWebRequest: 550 Dimensione non consentita in modalità ASCII

Ora prima scarico un file fittizio per aprire la connessione. Vedi sotto

Grazie a tutti per il supporto.

Grande comunità. Grazie.

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