2010-02-24 6 views
5

Sto scaricando un file da un sito FTP (Async) e ho bisogno di aggiornare una barra di avanzamento. Ho letto la documentazione MS che afferma che questo può essere fatto è GetWebRequest() della classe WebClient è ovverriden così la proprietà 'UsePassive' è impostata su 'false'. Ho fatto questo, ma l'argomento dell'evento 'DownloadProgressChanged' ProgressPercentage è sempre == '0'.Come visualizzare il download del download da FTP

Qualcuno può dirmi come ottenere questo argomento per iniziare a restituire valori?

Questo è il metodo di download:

  FTPClient request = new FTPClient(); 
      request.Credentials = new NetworkCredential(user, password); 
      request.DownloadProgressChanged += UpdateProgress; 
      request.DownloadFileAsync(ftpepath,destinationpath); 

Questo è il FTPClient (dove sto imperativi GetWebRequest()):

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

E la mia richiamata se aiuta:

void UpdateProgress(object sender, DownloadProgressChangedEventArgs e) 
     { 
      dwnProgress.Value = e.ProgressPercentage; 
      dwnprcnt.Text = PercentProgress.ToString() + "%"; 
     } 
+0

Per mostrare lo stato di avanzamento è necessario chiamare la funzione in un thread separato in modo che non bloccare l'interfaccia utente dell'applicazione se il suo favore o pagina web. –

risposta

3

UsePassive viene utilizzato per "determinare" chi funge da server quando viene effettuata la connessione per il trasferimento file , quindi non dovrebbe avere nulla a che fare con lo stato attuale del trasferimento. Posso chiederti dove hai letto questo?

Potrebbe essere che

  • il cambiamento è molto piccolo per un file di grandi dimensioni, in modo da non vedere il percentagechanged?
  • che il file è più piccolo del buffer interno ftpwebrequests in modo da ottenere l'intero file prima di qualsiasi "aggiornamento"?

È possibile impostare un punto di interruzione in UpdateProgress e vedere qualcosa nelle proprietà di e?

E come nota a margine, dal momento che si sta scaricando il file async, viene utilizzato un altro thread per il download effettivo. Nel suo metodo di evento, probabilmente si vuole fare qualcosa di simile:

void UpdateProgress(object sender, DownloadProgressChangedEventArgs e) { 
    setProgress(e.ProgressPercentage); 
    setText(e.ProgressPercentage.ToString() + "%"); 
} 

private void setProgress(int progress){ 
    if (dwnProgress.InvokeRequired) { 
     dwnProgress.Invoke(new Action<int>(setProgress), progress); 
     return; 
    } 
    dwnProgress.Value = progress; 
} 

private void setText(string text) { 
    if (dwnprcnt.InvokeRequired) { 
     dwnprcnt.Invoke(new Action<string>(setText), text); 
     return; 
    } 
    dwnprcnt.Text = text; 
} 

Quale sarà la fila i setmethods al thread UI, invece.

2

ho voluto lasciare un commento al post di cui sopra, ma io sono troppo nuovo :(

riferimento a MSDN sul override del metodo di richiesta web:

http://msdn.microsoft.com/en-US/library/system.net.webclient.downloadprogresschanged(v=vs.80).aspx

Tuttavia, in risposta ai PO domanda se il tuo server FTP non è impostato per accettare connessioni attive quindi impostare WebClient.UsePassive = false non farà alcuna differenza

EDIT: ho abilitato System.Net.Tracing sul mio progetto e ho provato sia passivo sia d modalità attive e non solo entrambe funzionano come previsto ... TotalBytes è ancora -1 quindi il mio pensiero è la nota su MSDN in errore o ci manca qualcosa

The DownloadFileProgressChangedEventArgs contiene i byte totali ricevuti e se si sa la dimensione del file puoi calcolarti.

Probabilmente c'è un modo migliore ... Ma ho usato un veloce FtpWebRequest per ottenere le dimensioni del file e poi passare questo al metodo DownloadProgressCallback per aggiornare la barra di avanzamento.

Anche ciò che il precedente manifesto non ha menzionato è che il metodo di avanzamento dell'aggiornamento deve richiamare il controllo perché viene chiamato dal thread creato da DownloadFileAsync e puoi solo modificare un controllo dal thread che lo ha creato.

È necessario utilizzare il dispatcher per il controllo ad es.

if (!myCheckBox.Dispatcher.CheckAccess()) 
{ 
    myCheckBox.Dispatcher.BeginInvoke(new Action(
    delegate() 
    { 
     myCheckBox.IsChecked = true; 
    } 
    )); 
} 
else 
{ 
    myCheckBox.IsChecked = true; 
} 

Vedi http://msdn.microsoft.com/en-us/library/ms591206.aspx