2011-01-04 9 views
6

Ich versuche, eine Datei von einem FTP-Server mit einer Fortschrittsanzeige herunterzuladen.Datei von FTP mit Progress herunterladen - TotalBytesToReceive ist immer -1?

Die Datei wird heruntergeladen, und das Ereignis Progress anruft, außer im Falle args TotalBytesToReceive ist immer -1. TotalBytes erhöht, aber ich kann den Prozentsatz ohne die Summe nicht berechnen.

Ich stelle mir vor, ich könnte die Dateigröße durch andere FTP-Befehle finden, aber ich frage mich, warum das nicht funktioniert?

Mein Code:

FTPClient request = new FTPClient(); 
request.Credentials = credentials; 
request.DownloadProgressChanged += new DownloadProgressChangedEventHandler(request_DownloadProgressChanged); 
//request.DownloadDataCompleted += new DownloadDataCompletedEventHandler(request_DownloadDataCompleted); 
request.DownloadDataAsync(new Uri(folder + file)); 
while (request.IsBusy) ; 

....

static void request_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) 
{ 
    if (e.TotalBytesToReceive == -1) 
    { 
     l.reportProgress(-1, FormatBytes(e.BytesReceived) + " out of ?"); 
    } 
    else 
    { 
     l.reportProgress(e.ProgressPercentage, "Downloaded " + FormatBytes(e.BytesReceived) + " out of " + FormatBytes(e.TotalBytesToReceive) + " (" + e.ProgressPercentage + "%)"); 
    } 
} 

....

class FTPClient : WebClient 
{ 
    protected override WebRequest GetWebRequest(System.Uri address) 
    { 
     FtpWebRequest req = (FtpWebRequest)base.GetWebRequest(address); 
     req.UsePassive = false; 
     return req; 
    } 
} 

Dank. tun dies auf eigene Faust

+0

Es scheint Ihnen eine bessere Umsetzung zu bieten haben 'WebClient', um damit umzugehen. Suchen Sie nach interessanten Eigenschaften/Methoden zum Überschreiben. – leppie

+0

Hatte einen Blick auf 'WebClient', aber es scheint nahezu unmöglich, ohne viele Hacks zu implementieren. – leppie

Antwort

-1

FTP Wont geben Sie Inhalte Größen wie HTTP funktioniert, würden Sie wahrscheinlich besser sein.

FtpWebRequest FTPWbReq = WebRequest.Create("somefile") as FtpWebRequest; 
FTPWbReq .Method = WebRequestMethods.Ftp.GetFileSize; 

FtpWebResponse FTPWebRes = FTPWbReq.GetResponse() as FtpWebResponse; 
long length = FTPWebRes.ContentLength; 
FTPWebRes.Close(); 
4

Also hatte ich das gleiche Problem. Ich habe es umgangen, indem ich zuerst die Dateigröße abgerufen habe.

 // Get the object used to communicate with the server. 
     FtpWebRequest request = (FtpWebRequest)WebRequest.Create("URL"); 
     request.Method = WebRequestMethods.Ftp.GetFileSize; 
     request.Credentials = networkCredential; 
     FtpWebResponse response = (FtpWebResponse)request.GetResponse(); 

     Stream responseStream = response.GetResponseStream(); 
     bytes_total = response.ContentLength; //this is an int member variable stored for later 
     Console.WriteLine("Fetch Complete, ContentLength {0}", response.ContentLength); 
     response.Close(); 

     webClient = new MyWebClient(); 
     webClient.Credentials = networkCredential; ; 
     webClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(FTPDownloadCompleted); 
     webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(FTPDownloadProgressChanged); 
     webClient.DownloadDataAsync(new Uri("URL")); 

Dann tun Sie die Mathematik im Rückruf.

private void FTPDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) 
{ 
    progressBar.Value = (int)(((float)e.BytesReceived/(float)bytes_total) * 100.0); 
} 
0

Lösung mit FtpWebRequest und Task:

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

enter image description here

Der Downloadcode Kern basiert auf:
Upload and download a binary file to/from FTP server in C#/.NET