First, you should add the following directives:
Listing 1 - Directives
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.
1.
Create an FtpWebRequest object over an ftp server URI.
2.
Set the FTP method to execute (upload, download, etc.).
3.
Set the options (SSL support, transfer as binary/not etc.) for the FTP
webrequest.
4.
Set the login credentials (username, password).
5.
Execute the request.
6.
Receive the response stream (if required).
7.
Close the FTP Request, in addition to any open streams.
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 properties 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:
Credentials - Specifies the username and password to login
to the FTP server.
KeepAlive - Specifies if the control connection should be
closed or not after the request is completed. By default it is set to true.
UseBinary - Denotes the datatype for file transfers. The 2
modes of file transfer in this case are Binary and ASCII. At bit level both
vary in the 8th bit of a byte. ASCII uses 8th bit as insignificant bit for
error control, where as, for binary all the 8 bits are significant. So take
care when you go for the ASCII transmission. To be simple, all those files that
open and read well in notepad are safe as ASCII. Executables, formatted docs,
etc. should be sent using binary mode. BTW sending ASCII files as binary works
fine most of the time.
UsePassive - Specifies to use either active or passive mode.
Earlier active FTP worked fine with all clients, but now a days as most of the
random ports will blocked by firewall and the active mode may fail. The passive
FTP is helpful in this case, but still it causes issues at the server. The
higher ports requested by client on server may also be blocked by firewall. But
since FTP servers will need to make their servers accessible to the greatest
number of clients, they will almost certainly need to support passive FTP. The
reason why passive mode is considered safe is that it ensures all data flow
initiation comes from inside (client) the network rather than from the outside (server).
Contentlength - Setting this property is useful for the
server we request to, but is not of much use for us (client) because
FtpWebRequest usually ignores this property value, so it will not be available
for our use in most of the cases. If we set this property, the FTP server will
get an idea in advance about the size of the file it should expect (in case of
upload).
Method - Denotes what action (command) to take in the
current request (upload, download, filelist, etc.). It is set a value defined
in the WebRequestMethods.Ftp structure.
Listing 2 - Upload
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[buffLength];
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 smaller files.
Listing 3 - Download
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[bufferSize];
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 in turn 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 that 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.
Listing 4 – Retrieve Filelist on FTP Server
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." this is the 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 string
array and returned. I am sure there are better ways to do it like removing the
whole '\r" instances from the whole list (returned by
<<StreamReader>>.ReadToEnd())) and split the resultant string uisng
"\n" delimiter. Anyway, I did not 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.