Introduction
The Microsoft .NET framework provides a powerful library to access FTP sites and their content. In this article, we discuss how to access them from within web application and stream files from FTP and dump them wherever you want.
Using the code
The code has two parts:
- FTP Helper - The project containing files for the FTP methods.
- FTP Web - The web application for FTP.
The FTPConnection
class must be serialized because I use it in the ViewState.
[Serializable]
public class FTPConnection
Here is the method used to connect to an FTP site:
public FtpWebRequest ConnectToFtp(string Method)
{
FtpWebRequest ftpRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(_url));
ftpRequest.UseBinary = true;
ftpRequest.Credentials = new NetworkCredential(_username, _password);
ftpRequest.Method = Method;
ftpRequest.Proxy = null;
ftpRequest.KeepAlive = false;
ftpRequest.UsePassive = false;
return ftpRequest;
}
Now we can get the files list including the name and fully qualified paths from a specific URL:
public Dictionary<string, string> GetFileList(string FolderUrl)
{
StringBuilder filesstring = new StringBuilder();
WebResponse webResponse = null;
StreamReader sreader = null;
Dictionary<string, string> Files = new Dictionary<string, string>();
try
{
FtpWebRequest ftpRequest = ConnectToFtp(FolderUrl,
WebRequestMethods.Ftp.ListDirectory);
webResponse = ftpRequest.GetResponse();
sreader = new StreamReader(webResponse.GetResponseStream());
string strline = sreader.ReadLine();
while (strline != null)
{
Files.Add(strline, FolderUrl +"/"+ strline);
}
return Files;
}
catch (Exception ex)
{
return null;
}
finally
{
if (sreader != null)
{
sreader.Close();
}
if (webResponse != null)
{
webResponse.Close();
}
}
}
Here is how we get the downloadable file bytes:
public byte[] DownloadFileFromFtp(string fileUrl)
{
StringBuilder filesstring = new StringBuilder();
WebResponse webResponse = null;
try
{
FtpWebRequest ftpRequest = ConnectToFtp(fileUrl,
WebRequestMethods.Ftp.DownloadFile);
ftpRequest.UseBinary = true;
webResponse = ftpRequest.GetResponse();
FtpWebResponse response = (FtpWebResponse)webResponse;
Stream dfileResponseStream = response.GetResponseStream();
int Length = 1024;
Byte[] buffer = new Byte[Length];
List<byte> filebytes = new List<byte>();
int bytesRead = dfileResponseStream.Read(buffer, 0, Length);
while (bytesRead > 0)
{
for(int i= 0;i<bytesRead;i++)
filebytes.Add(buffer[i]);
bytesRead = dfileResponseStream.Read(buffer, 0, Length);
}
response.Close();
return filebytes.ToArray(); }
catch (Exception ex)
{
return null;
}
finally
{
if (webResponse != null)
{
webResponse.Close();
}
}
}
We are done with the basic FTP methods. We will now look at the web application part.
I store the FTPHelper.FTPConnection
object in the ViewState, because I want to use the same instance multiple times on a page.
public FTPHelper.FTPConnection FTP
{
set
{
ViewState["FTP"] = value;
}
get
{
return ViewState["FTP"] == null ? null :
(FTPHelper.FTPConnection)ViewState["FTP"];
}
}
Set the FTP URL, username, and password for the FTP site using the interface below:
Now connect to the FTP site and retrieve the root directories and files:
public void ConnectToFtp()
{
try
{
FTP = new FTPHelper.FTPConnection(txtFTPUrl.Text.ToLower().Replace(
"ftp://",""), txtUser.Text, txtPassword.Text);
Dictionary<string, string> Files = FTP.GetFileList(FTP._url);
lblWelcome.Text = "<strong> Welcome </strong> " + txtUser.Text;
tbLogin.Visible = false;
foreach (string ky in Files.Keys)
{
TreeNode trParent = new TreeNode();
trParent.Text = (string)ky; trParent.Value = Files[ky];
trVFiles.Nodes.Add(trParent);
}
}
catch(Exception ex)
{
tbLogin.Visible = false;
lblWelcome.Text = ex.Message;
lblWelcome.ForeColor = System.Drawing.Color.Red;
}
}
Capture the SelectedNodeChanged
event of the TreeView
control to get the directory and files in the selected directory node:
protected void trVFiles_SelectedNodeChanged(object sender, EventArgs e)
{
Dictionary<string,string> _filesInFolder = FTP.GetFileList(trVFiles.SelectedValue);
Dictionary<string, string> _onlyfiles = new Dictionary<string, string>();
foreach (string key in _filesInFolder.Keys)
{
if (key.IndexOf('.') == -1)
{
TreeNode trParent = new TreeNode();
trParent.Text = (string)key;
trParent.Value = _filesInFolder[key];
trVFiles.SelectedNode.ChildNodes.Add(trParent);
}
else
{
_onlyfiles.Add(key, _filesInFolder[key]); }
}
trVFiles.SelectedNode.Expand(); BindGrid(_onlyfiles); }
Finally, get the RowCommand
event to download the desired file:
protected void grdDetailView_RowCommand(object sender, GridViewCommandEventArgs e)
{
byte[] _downFile = FTP.DownloadFileFromFtp(e.CommandArgument.ToString());
string _fname =e.CommandArgument.ToString();
Response.ContentType = "application/"+_fname.Split('.')[1];
Response.AddHeader("Content-disposition",
"attachment; filename=" + _fname);
Response.OutputStream.Write(_downFile, 0, _downFile.Length);
Response.End();
}
That's all.