2010-02-24 11 views
5

Pobierany jest plik z witryny FTP (Async) i trzeba zaktualizować pasek postępu. Przeczytałem dokumentację MS, która stwierdza, że ​​można to zrobić, to GetWebRequest() klasy WebClient jest ovverriden, więc właściwość "UsePassive" jest ustawiona na "false". Zrobiłem to, ale argument zdarzenia "DownloadProgressChanged" ProgressPercentage jest zawsze == '0'.Jak wyświetlić postęp pobierania z FTP

Czy ktoś może mi powiedzieć, jak uzyskać ten argument, aby rozpocząć zwracanie wartości?

Jest to metoda pobierania:

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

To FTPClient (gdzie jestem nadrzędnymi GetWebRequest()):

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

i mój oddzwanianie czy to pomaga:

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

Aby pokazać postęp trzeba wywołać funkcję w osobnym wątku, więc nie blokuje UI aplikacji czy jego rzecz lub strona internetowa. –

Odpowiedz

3

UsePassive służy do "ustalenia", kto działa jako serwer, gdy nawiązane jest połączenie do transferu plików , więc nie powinno to mieć nic wspólnego z faktycznym statusem przelewu. Czy mogę zapytać, gdzie to przeczytałeś?

Czyżby

  • zmiana jest bardzo mały dla dużego pliku, więc nie zobaczyć percentagechanged?
  • że plik jest mniejszy niż ftpwebrequests wewnętrzny bufor, więc dostajesz cały plik przed jakąkolwiek "aktualizacją"?

Czy można ustawić punkt przerwania w UpdateProgress i zobaczyć cokolwiek we właściwościach e?

Na marginesie, ponieważ pobierasz asynchroniczny plik, do pobrania jest używany inny wątek. W swojej metodzie zdarzeń prawdopodobnie chcesz zrobić coś takiego:

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

Które kolejce setmethods do wątku UI zamiast.

2

Chciałem komentarz do powyższego postu opuścić, ale jestem zbyt nowe :(

Odniesienie do MSDN na nadpisanie metody żądania Web:

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

Jednak w odpowiedzi na PO pytanie, czy twój serwer FTP nie jest ustawiony, aby zaakceptować aktywne połączenia następnie ustawienie WebClient za pomocą UsePassive = false nie będzie miało znaczenia

EDYCJA: Włączam System.Net.Tracing na moim projekcie i próbowałem zarówno pasywne i d tryby aktywne i nie tylko działają zgodnie z oczekiwaniami ... TotalBytes to nadal -1, więc moje myślenie jest błędną notatką na MSDN lub brakuje czegoś

The DownloadFileProgressChangedEventArgs zawierają całkowitą liczbę otrzymanych bajtów i jeśli wiesz rozmiar pliku, który możesz sam obliczyć.

Prawdopodobnie istnieje lepszy sposób ... Ale użyłem szybkiego FtpWebRequest, aby uzyskać rozmiar pliku, a następnie przekazać go do metody DownloadProgressCallback, aby zaktualizować pasek postępu.

Nie można również wspomnieć o powyższym plakacie, ponieważ metoda postępu aktualizacji musi wywołać formant, ponieważ jest wywoływana przez wątek utworzony przez DownloadFileAsync i można zmienić tylko formant z wątku, który go utworzył.

Powinieneś użyć kontrolera do kontroli, np.

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

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

Powiązane problemy