2011-01-04 20 views
6

Estoy intentando descargar un archivo de un servidor FTP con una barra de progreso.Descargar archivo de FTP con progreso - TotalBytesToReceive es siempre -1?

El archivo se está descargando, y el evento ProgressChanged llama, excepto en el caso de que args TotalBytesToReceive siempre sea -1. TotalBytes aumenta, pero no puedo calcular el porcentaje sin el total.

Me imagino que podría encontrar el tamaño del archivo a través de otros comandos ftp, pero me pregunto por qué no funciona.

Mi código:

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

Gracias.

+0

Parece que tendrá que proporcionar una mejor aplicación de las 'WebClient' para manejar eso. Busque propiedades/métodos interesantes para anular. – leppie

+0

Eché un vistazo a 'WebClient', pero parece casi imposible de implementar sin muchos hacks. – leppie

Respuesta

-1

FTP No le proporcionaremos los tamaños de contenido como lo hace HTTP, probablemente sería mejor hacerlo por su cuenta.

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

Así que tuve el mismo problema. Lo solucioné recuperando primero el tamaño del archivo.

 // 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")); 

Luego haga los cálculos en la devolución de llamada.

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

solución utilizando FtpWebRequest y 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

se basa el código de descarga central en:
Upload and download a binary file to/from FTP server in C#/.NET

Cuestiones relacionadas