I've done quite a bit of work with FTPwebrequest and i share your feelings about the lack of documentation but it's a new feature so it's to be expected. Here i go and try, if there any errors the MS guys are welcome to edit this thread:
First you need to create a REQUEST, this is done through the myFtpWebRequest.Create("MyConnectString") where MyConnectString is something like "ftp://" + userName + ":" + password + "@" + serverAddress + ":" + serverPort + "/" + fileToUpload.ToString
Now keep in mind you haven't actually connected to the FTP server yet, you have just created this ftpwebrequest object.
Next you have to set the ftpwebrequest to do what you want for example:
request.Timeout = 10000
request.ReadWriteTimeout = 10000
request.KeepAlive = False
request.UseBinary = True
request.Method = WebRequestMethods.Ftp.ListDirectory
The above should be pretty self explanatory.
Now that you have the ftpwebrequest set up, now you want to connect to the ftp server and get its "response", the response being the directory listing like my example above.
And then you can access the stream that is returned.
myFtpWebResponse.GetResponse
dirContents = myFtpWebResponse.GetResponseStream
In this case it makes sense because you want to get the response to your request of the specified directory's contents. To download a file synchronously you set the method to DownloadFile, then get the response stream and put it into whatever you wish.
For other FTP operations it gets a little dicey. If you wanted to create a directory on the server, you create a ftpwebrequest with its method set to create a directory.
myFtpWebRequest.Method = WebRequestMethods.Ftp.MakeDirectory
Now remember you haven't even connected to the server yet. You need to call the .getResponse in order to connect and create the directory.
myFtpWebResponse = myFtpWebRequest.GetResponse
At this point the directory is created on the server. You can get the server's OK or ERROR
message this way.
myStatus = myFtpWebResponse.StatusDescription
So the thing you need to remember is that there is no connection is made, and no command is sent to the server until you call the .GetResponse on the ftpwebrequest. Then depending on what .method you selected for your ftpwebrequest, you can access the stream for data returned or perhaps a status code.
Now the big one is the asynchronous uploading and downloading. Synchronous uploading or downloading of data via .GetResponse is non-productive as it will lock up your GUI thread (if you run the .GetResponseStream, not allowing you to move the window or edit data whilst downloading/uploading, and not allow you to make update a progress bar or current up/down speeds.
There is an excellent example of implementing async uploading here, it is in c# but you can easily convert it to vb.net if you need too, i'm a newb and it took me about half an hour as all the errors are underlined :)
In your VS 2005 Help:
ms-help://MS.VSExpressCC.v80/MS.NETFramework.v20.en/cpref10/html/
T_System_Net_FtpWebRequest.htm
On the net:
http://msdn2.microsoft.com/en-us/library/system.net.ftpwebrequest(VS.80).aspx
Hopefully this helps you out, I had a difficult time grasping it myself, as I couldn't figure out why i had to always relogin to the server to upload the next file, but that is how this class works.
***Edited ***
After fooling around with my program i've come across some great news. You CAN use the initial ftp connection to upload more than one file. Let me explain in some more detail. I have an app that will take in a file list and determine what directories need to be created on the server and what files need to be uploaded to the server.
Here is some pseudocode:
While directories left to create {
myRequest = FtpWebRequest.Create(ServerAddress/DirToCreate)
myRequest.method = CreateDirectory
myRequest.keepAlive = True
myResponse = myRequest.GetResponse
myStatus = myRequest.StatusDescription
goto next dir to create
}
While files left to send {
myRequest = FtpWebRequest.Create(ServerCreate/FileToSend)
myRequest.method = UploadFile
if last file to send {
myRequest.keepAlive = False
}
else {
myRequest.keepAlive = False
}
'start asynchronous uploading
myRequest.BeginGetRequestStream(New AsyncCallback _
(AddressOf EndGetStreamCallback), State)
'wait until the upload is finish
waitObject.WaitOne()
goto next file to upload
}
If i checked the server's log file i can verify that there was only one "login " procedure, it used the same initial connection to create the directories and all the files. There were a few other USERNAME , PASSWORD commands (1 for every 10 files or so) but no "Connected to x.y.z.a" and no "Closing connection for user XYZ" and at no time did i notice two of the same user logged in twice so i surmise that it is just periodically sending USERNAME and PASWORD commands but not disconnecting / reconnecting. This is great news as now we can compete with normal ftp clients in terms of speed when dealing with a large amount of small files.
One thing to note is that if any of your .getResponse call throws an exception, it will kill the current connection to the ftp and create a new one for your next .getResponse() call. Keep in mind that exceptions in this case can be invalid paths to or for a file, or even trying to create a directory that already exists. If i run the above code a second time, i get exceptions as its trying to create the directories that were created on the first run. If i check the ftp log, there will be a disconnection with a "Directory already exists" ftp message, then a reconnection to try the next ftp operation. So if you create 4 directories on the first run, you will get 4 exceptions and 4 reconnects the second run. Not a big deal and doesn't really slow you down that much. Just keep in mind that an exception is this case does not necessarily mean a fatal error, it just means that the .method could not accomplish its mission with the ServerAddress/FileDirName information it was created with.
Alot of people are complaining about the FTPWEBREQUEST in net 2.0. I disagree, it allows us to do alot of ftp commands with little programming and alot of helpful abstraction. The only think i could ask for would be a built in asynchronous transfer module/class. The example provided with msdn worked well for me, but it is really daunting to look at the first time. Plus, there won't be too many people interested in sync transfers as you cannot provide transfer speed or transfer progress feedback to the user.
Great job on this MS, the Express Edition 2.0 Free Trial idea is awesome. It allows people like me, CS degree but little real coding experience, to jump in there and learn while being able to get results quickly and with alot of avenues to get help. Never have i felt lost or have had the feeling that i was stuck, which is key for beginner coder.
See also:
Understanding System.Net Connection Management and ServicepointManager
First you need to create a REQUEST, this is done through the myFtpWebRequest.Create("MyConnectString") where MyConnectString is something like "ftp://" + userName + ":" + password + "@" + serverAddress + ":" + serverPort + "/" + fileToUpload.ToString
Now keep in mind you haven't actually connected to the FTP server yet, you have just created this ftpwebrequest object.
Next you have to set the ftpwebrequest to do what you want for example:
request.Timeout = 10000
request.ReadWriteTimeout = 10000
request.KeepAlive = False
request.UseBinary = True
request.Method = WebRequestMethods.Ftp.ListDirectory
The above should be pretty self explanatory.
Now that you have the ftpwebrequest set up, now you want to connect to the ftp server and get its "response", the response being the directory listing like my example above.
And then you can access the stream that is returned.
myFtpWebResponse.GetResponse
dirContents = myFtpWebResponse.GetResponseStream
In this case it makes sense because you want to get the response to your request of the specified directory's contents. To download a file synchronously you set the method to DownloadFile, then get the response stream and put it into whatever you wish.
For other FTP operations it gets a little dicey. If you wanted to create a directory on the server, you create a ftpwebrequest with its method set to create a directory.
myFtpWebRequest.Method = WebRequestMethods.Ftp.MakeDirectory
Now remember you haven't even connected to the server yet. You need to call the .getResponse in order to connect and create the directory.
myFtpWebResponse = myFtpWebRequest.GetResponse
At this point the directory is created on the server. You can get the server's OK or ERROR
message this way.
myStatus = myFtpWebResponse.StatusDescription
So the thing you need to remember is that there is no connection is made, and no command is sent to the server until you call the .GetResponse on the ftpwebrequest. Then depending on what .method you selected for your ftpwebrequest, you can access the stream for data returned or perhaps a status code.
Now the big one is the asynchronous uploading and downloading. Synchronous uploading or downloading of data via .GetResponse is non-productive as it will lock up your GUI thread (if you run the .GetResponseStream, not allowing you to move the window or edit data whilst downloading/uploading, and not allow you to make update a progress bar or current up/down speeds.
There is an excellent example of implementing async uploading here, it is in c# but you can easily convert it to vb.net if you need too, i'm a newb and it took me about half an hour as all the errors are underlined :)
In your VS 2005 Help:
ms-help://MS.VSExpressCC.v80/MS.NETFramework.v20.en/cpref10/html/
T_System_Net_FtpWebRequest.htm
On the net:
http://msdn2.microsoft.com/en-us/library/system.net.ftpwebrequest(VS.80).aspx
Hopefully this helps you out, I had a difficult time grasping it myself, as I couldn't figure out why i had to always relogin to the server to upload the next file, but that is how this class works.
***Edited ***
After fooling around with my program i've come across some great news. You CAN use the initial ftp connection to upload more than one file. Let me explain in some more detail. I have an app that will take in a file list and determine what directories need to be created on the server and what files need to be uploaded to the server.
Here is some pseudocode:
While directories left to create {
myRequest = FtpWebRequest.Create(ServerAddress/DirToCreate)
myRequest.method = CreateDirectory
myRequest.keepAlive = True
myResponse = myRequest.GetResponse
myStatus = myRequest.StatusDescription
goto next dir to create
}
While files left to send {
myRequest = FtpWebRequest.Create(ServerCreate/FileToSend)
myRequest.method = UploadFile
if last file to send {
myRequest.keepAlive = False
}
else {
myRequest.keepAlive = False
}
'start asynchronous uploading
myRequest.BeginGetRequestStream(New AsyncCallback _
(AddressOf EndGetStreamCallback), State)
'wait until the upload is finish
waitObject.WaitOne()
goto next file to upload
}
If i checked the server's log file i can verify that there was only one "login " procedure, it used the same initial connection to create the directories and all the files. There were a few other USERNAME , PASSWORD commands (1 for every 10 files or so) but no "Connected to x.y.z.a" and no "Closing connection for user XYZ" and at no time did i notice two of the same user logged in twice so i surmise that it is just periodically sending USERNAME and PASWORD commands but not disconnecting / reconnecting. This is great news as now we can compete with normal ftp clients in terms of speed when dealing with a large amount of small files.
One thing to note is that if any of your .getResponse call throws an exception, it will kill the current connection to the ftp and create a new one for your next .getResponse() call. Keep in mind that exceptions in this case can be invalid paths to or for a file, or even trying to create a directory that already exists. If i run the above code a second time, i get exceptions as its trying to create the directories that were created on the first run. If i check the ftp log, there will be a disconnection with a "Directory already exists" ftp message, then a reconnection to try the next ftp operation. So if you create 4 directories on the first run, you will get 4 exceptions and 4 reconnects the second run. Not a big deal and doesn't really slow you down that much. Just keep in mind that an exception is this case does not necessarily mean a fatal error, it just means that the .method could not accomplish its mission with the ServerAddress/FileDirName information it was created with.
Alot of people are complaining about the FTPWEBREQUEST in net 2.0. I disagree, it allows us to do alot of ftp commands with little programming and alot of helpful abstraction. The only think i could ask for would be a built in asynchronous transfer module/class. The example provided with msdn worked well for me, but it is really daunting to look at the first time. Plus, there won't be too many people interested in sync transfers as you cannot provide transfer speed or transfer progress feedback to the user.
Great job on this MS, the Express Edition 2.0 Free Trial idea is awesome. It allows people like me, CS degree but little real coding experience, to jump in there and learn while being able to get results quickly and with alot of avenues to get help. Never have i felt lost or have had the feeling that i was stuck, which is key for beginner coder.
See also:
Understanding System.Net Connection Management and ServicepointManager