Reusing FtpWebRequest
.net, c#, ftp, ftpwebrequest
Solution
I don't think this will be answered so I'm "closing it" by telling you how I solved it.
Well, I didn't really solve it. I did however test the download by recreating the `FtpWebRequest` and noticed that on the FTP server it behaved as I wanted i.e. only one log on and then sequentially executing my requests.
This is how the code getting the file size and starting the download ended up:
// Start by fetching the file size
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(sURI);
request.Method = WebRequestMethods.Ftp.GetFileSize;
NetworkCredential nc = new NetworkCredential(sUser, sPwd);
request.Credentials = nc;
request.UseBinary = true;
request.UsePassive = true;
request.KeepAlive = true;
// Get the result (size)
FtpWebResponse resp = (FtpWebResponse)request.GetResponse();
Int64 contLen = resp.ContentLength;
// and now download the file
request = (FtpWebRequest)FtpWebRequest.Create(sURI);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = nc;
request.UseBinary = true;
request.UsePassive = true;
request.KeepAlive = true;
resp = (FtpWebResponse)request.GetResponse();
So no answer on if it's possible to reset the `FtpWebRequest` for re-use. But at least I know there's no redundant information being transferred.
Thanks to everybody who took an interest and spent time thinking of an answer.
Problem
I'm trying to make a simple method to download a file from an FTP using `FtpWebRequest` with the method `WebRequestMethods.Ftp.DownloadFile`. The problem is that I wan't to display the progress of downloading and thus need to know the file size ahead to be able to calculate the percentage transfered. But when I call `GetResponse` in `FtpWebRequest` the `ContentLength` member is -1. OK - so I get the size of the file in advance using the method `WebRequestMethods.Ftp.GetFileSize`. No problem. Then after getting the size I download the file. This is where the problem in question appears... After getting the size I try to reuse the `FtpWebRequest` and resets the method to `WebRequestMethods.Ftp.DownloadFile`. This causes an `System.InvalidOperationException` saying something like "Can't perform this action after sending the request." (may not be the exact formulation - translated from the one I get in Swedish). I've found elsewhere that as long as I set the `KeepAlive` property to true, it doesn't matter, the connection is kept active. This is what I don't understand... The only object I've created is my `FtpWebRequest` object. And if I create another one, how can it know what connection to use? And what credentials? Pseudo code: ``` 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 ``` Now I got the file size. So it's time to download the file. Setting Method now causes the exception mentioned above. So do I create a new `FtpWebRequest`? Or is there anyway to reset the request to be reused? (Closing the response made no difference.) I don't understand how to move forward without re-creating the object. I could do that, but it just doesn't feel right. So i'm posting here in hope to find the correct way of doing this. Here's the (non working) code (Inputs are sURI, sDiskName, sUser and 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(); ``` I hope someone can explain how this is supposed to work. Thanks in advance.