Próbuję wykonać prostą metodę pobrania pliku z FTP przy użyciu FtpWebRequest
za pomocą metody WebRequestMethods.Ftp.DownloadFile
. Problem polega na tym, że nie chcę wyświetlać postępu pobierania i dlatego muszę znać rozmiar pliku, aby móc obliczyć procent przeniesiony. Ale gdy zadzwonię pod numer GetResponse
w FtpWebRequest
, członkiem ContentLength
jest -1.Ponowne użycie FtpWebRequest
OK - otrzymam z góry rozmiar pliku przy użyciu metody WebRequestMethods.Ftp.GetFileSize
. Nie ma problemu. Następnie po uzyskaniu rozmiaru pobieram plik.
tym miejscu pojawia się problem w kwestii ...
Po uzyskaniu rozmiaru próbie ponownego użycia FtpWebRequest
i resetuje metodę WebRequestMethods.Ftp.DownloadFile
. Powoduje to, że System.InvalidOperationException
mówi coś w stylu "Nie można wykonać tej czynności po wysłaniu żądania." (może nie być dokładnym sformułowaniem - przetłumaczonym z tego, które dostaję po szwedzku).
Znalazłem gdzie indziej, że dopóki ustawiam właściwość KeepAlive
na true, nie ma to znaczenia, połączenie jest aktywne. Tego nie rozumiem ... Jedynym obiektem, który utworzyłem jest mój obiekt FtpWebRequest
. A jeśli utworzę inny, jak on może wiedzieć, z jakiego połączenia korzystać? I jakie referencje?
Pseudo kod:
Create FtpWebRequest
Set Method property to GetFileSize
Set KeepAlive property to true
Set Credentials property to new NetworkCredential(...)
Get FtpWebResponse from the request
Read and store ContentLength
Teraz mam rozmiar pliku. Czas więc pobrać plik. Ustawienie Metoda wiem powoduje wyjątek wspomniany powyżej. Czy mogę utworzyć nowy FtpWebRequest
? A może zresetować prośbę do ponownego użycia? (Zamknięcie odpowiedzi nie zrobiło żadnej różnicy.)
Nie rozumiem, jak posuwać się naprzód bez ponownego tworzenia obiektu. Mógłbym to zrobić, ale po prostu nie czuję się dobrze. Więc zamieszczam tutaj w nadziei, że znajdę właściwy sposób na zrobienie tego.
Oto (bez pracy) Kod (Wejścia są Suri, sDiskName, suser i spwd.):
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(sURI);
request.Method = WebRequestMethods.Ftp.GetFileSize;
request.Credentials = new NetworkCredential(sUser, sPwd);
request.UseBinary = true;
request.UsePassive = true;
request.KeepAlive = true;
FtpWebResponse resp = (FtpWebResponse)request.GetResponse();
int contLen = (int)resp.ContentLength;
resp.Close();
request.Method = WebRequestMethods.Ftp.DownloadFile;
resp = (FtpWebResponse)request.GetResponse();
Stream inStr = resp.GetResponseStream();
byte[] buff = new byte[16384];
sDiskName = Environment.ExpandEnvironmentVariables(sDiskName);
FileStream file = File.Create(sDiskName);
int readBytesCount;
int readTotal=0;
while ((readBytesCount = inStr.Read(buff, 0, buff.Length)) > 0)
{
readTotal += readBytesCount;
toolStripProgressBar1.Value = 100*readTotal/contLen;
Application.DoEvents();
file.Write(buff, 0, readBytesCount);
}
file.Close();
Mam nadzieję, że ktoś może wyjaśnić, jak to ma działać. Z góry dziękuję.
Przynajmniej za pomocą HTTPWebRequests - zawsze musisz utworzyć nowy. Załóżmy, że ten sam problem tutaj. – Hikiko
'FtpWebRequest' jest dobry do robienia pojedynczych żądań. Chcesz klienta FTP, który łączy i utrzymuje stałe połączenie, dopóki go nie zamkniesz. "System.Net.FtpClient" wydaje się być dobrze traktowany: http://netftp.codeplex.com/ –