
An addition to the Microsoft .NET framework 2.0 to 1.x is the support for FTP. All these days we had to rely on 3rd party libraries which pretty well suited most of our needs, but for sure, there is an extra pleasure using the .net framework library classes. The code included is not designed to be a fulfledged reusable library, but rather an easy to use and reusable pieces of code which is easily comprehensible and can be reused and tweaked to fit your specific needs. Therefore the code for each functionality(upoad, download, delete etc..) can be easy picked up separately and reused. The main motive behind this article was the unavailability of .net2.0 ftp sample codes and their usage in C#; may be because its a new entrant to the .net scenario, or the third party implementations available were working pretty well, that this area of the .net2.0 library haven't got enough focus.
I started working on this FTP module as part of my official work, but the requirement soon changed and I had to do it for .net 1.1. So, I haven't travelled deeper into the rabbit hole. But I believe this gives a good, instant start for using the FTP support in .net 2.0.
Don't forget to add the following directive:
using System.Net;
using System.IO;
The following steps can be considered as a generic procedure of getting an FTP
request executed using FtpWebRequest object:
FtpWebRequest
object over an ftp server Uri
One point to watch out while coding for any ftp application is to have the
settings for the ftp request proper to suit the ftp server and its specific
configurations. FtpWebRequest object exposes many poperties to
have these settings in place.
The sample for the upload functionality is as follows:
First a uri is created which represents the ftp address along with the
filename(directory structure included). This uri is used to create the FtpWebRequest
instance.
Then properties of the FtpWebRequest object are set, which
determines the settings for the ftp request. Some of its important properties are:
private void Upload(string filename)
{
FileInfo fileInf = new FileInfo(filename);
string uri = "ftp://" + ftpServerIP + "/" + fileInf.Name;
FtpWebRequest reqFTP;
// Create FtpWebRequest object from the Uri provided
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(
"ftp://" + ftpServerIP + "/" + fileInf.Name));
// Provide the WebPermission Credintials
reqFTP.Credentials = new NetworkCredential(ftpUserID,
ftpPassword);
// By default KeepAlive is true, where the control connection is
// not closed after a command is executed.
reqFTP.KeepAlive = false;
// Specify the command to be executed.
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
// Specify the data transfer type.
reqFTP.UseBinary = true;
// Notify the server about the size of the uploaded file
reqFTP.ContentLength = fileInf.Length;
// The buffer size is set to 2kb
int buffLength = 2048;
byte[] buff = new byte;
int contentLen;
// Opens a file stream (System.IO.FileStream) to read
the file to be uploaded
FileStream fs = fileInf.OpenRead();
try
{
// Stream to which the file to be upload is written
Stream strm = reqFTP.GetRequestStream();
// Read from the file stream 2kb at a time
contentLen = fs.Read(buff, 0, buffLength);
// Till Stream content ends
while (contentLen != 0)
{
// Write Content from the file stream to the
// FTP Upload Stream
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
// Close the file stream and the Request Stream
strm.Close();
fs.Close();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Upload Error");
}
}
Above is a sample code for FTP Upload (PUT). The underlying sub command used is
STOR. Here an FtpWebRequest object is made for the specified file on the ftp
server. Different properties are set for the request namely Credentials,
KeepAlive, Method, UseBinary, ContentLength.
The file in our local machine is opened and the contents are written to the FTP
request stream. Here a buffer of size 2kb is used as an appropriate size suited
for upload of larger or smaler files.
private void Download(string filePath, string fileName)
{
FtpWebRequest reqFTP;
try
{
//filePath = <<The full path where the
//file is to be created. the>>,
//fileName = <<Name of the file to be createdNeed not
//name on FTP server. name name()>>
FileStream outputStream = new FileStream(filePath +
"\\" + fileName, FileMode.Create);
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" +
ftpServerIP + "/" + fileName));
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID,
ftpPassword);
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte;
readCount = ftpStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
ftpStream.Close();
outputStream.Close();
response.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Above is a sample code for Download of file from the FTP server. Unlike the
Upload functionality described above, Download would require the response
stream, which will contain the content of the file requested.
Here the file to download is specified as part of the Uri which inturn is used
for the creation of the FtpWebRequest object. To 'GET' the file
requested, get the response of the FtpWebRequest object using GetResponse()
method. This new response object built provides the response stream which
contain the file content as stream, which you can easily convert to a file
stream to get the file in place.
Note: We have the flexibility to set the location and name of the file under
which it is to be saved on our local machine.
public string[] GetFileList()
{
string[] downloadFiles;
StringBuilder result = new StringBuilder();
FtpWebRequest reqFTP;
try
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(
"ftp://" + ftpServerIP + "/"));
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID,
ftpPassword);
reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
WebResponse response = reqFTP.GetResponse();
StreamReader reader = new StreamReader(response
.GetResponseStream());
string line = reader.ReadLine();
while (line != null)
{
result.Append(line);
result.Append("\n");
line = reader.ReadLine();
}
// to remove the trailing '\n'
result.Remove(result.ToString().LastIndexOf('\n'), 1);
reader.Close();
response.Close();
return result.ToString().Split('\n');
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
downloadFiles = null;
return downloadFiles;
}
}
Above is a sample block of code for getting the file list on the ftp server. The
Uri is built specifying the FTP server address/name and the required path if
any. In the above example the root folder is specified for the creation of the
FtpWebRequest object. Here the response stream is used for the
creation of a StreamReader object, which has the whole list of
file names on the server separated by "\r\n" which is newline and
carriagereturn together. You can get the whole file list ("\r\n" separated)
using the ReadToEnd() method of the StreamReader object. The above
implementation, reads each file name and creates a StringBuilder object
by appending each file name. The resultant StringBuilder object is
split into a stirng array and returned. I am sure there are better ways to do
it. A better could be to remove the whole '\r' instances from the whole list
(returned by <<StreamReader>>.ReadToEnd())) and split
the resultant string uisng '\n' delimiter. Anyway I didnt want to spend more of
my energy and time pondering over it ;-).
The implementations for Rename, Delete, GetFileSize,
FileListDetails, MakeDir are very similar to the
above pieces of code and the attached code is easily comprehensible.
Note: For Renaming, the new name can be assigned to the RenameTo property
of FtpWebRequest object. For MakeDirectory, the name of the new
directory can be specified as part of the Uri used to create FtpWebRequest
object.
Please take NOTE of the following points while coding in this area:
EnableSsl
property is true, all data and commands, including your user name and password
information, are sent to the server in clear text. Anyone monitoring network
traffic can view your credentials and use them to connect to the server. If you
are connecting to an FTP server that requires credentials and supports Secure
Sockets Layer (SSL), you should set EnableSsl to true.
SecurityException
exception is thrown.
GetResponse method.
When the requested operation completes, an FtpWebResponse object is returned.
The FtpWebResponse object provides the status of the operation and
any data downloaded from the server. That is,
StatusCode property of FtpWebResponse object provides the latest
status code returned by the FTP server.
StatusDescription property of FtpWebResponse object provides the
description of the status code returned.