Click here to Skip to main content
15,888,816 members
Articles / Programming Languages / C#
Article

FTP component written with fully managed code

Rate me:
Please Sign up or sign in to vote.
4.78/5 (61 votes)
7 May 20021 min read 860K   14.7K   178   251
A .NET FTP component

Recently, I needed to write a program which could automatically download files from an FTP server. Unfortunately the .NET Framework lacks good support for FTP services. Although a few companies have already written libraries which can be used directly, the price is really too high for poor men like me. As a result, I decided to write my own FTP library and here it is.

Disclaimer

This FTP component is an incomplete implementation of my design nor has it been fully tested. Please keep in mind it may contain bugs or even design flaws.

Connect to FTP server

C#
FtpSession session = new FtpSession();
session.Server = "localhost";
session.Port   = 21; //not required if using the default ftp port 21
session.Connect("anonymous", "someone@somewhere.com");

Enum subdirectories and files

C#
/*
* It is possible an incorrect list will be returned.
* In this case, you need to add your own regular expression to 
* interpret the list result (try to find it within ftpdirectory.cs)
*/
FtpDirectory root = session.RootDirectory;
foreach(FtpDirectory d in root.SubDirectories)
    //do something

    foreach(FtpFile f in root.Files)
        //do something

        /*
         * Only CurrentDirectory's item can be legally used.
         * Do not save down FtpDirectory and FtpFile for later use
         * unless you are sure they belongs to CurrentDirectory.
         * Here is some sample may cause problems
         */
        FtpDirectory d1 = session.CurrentDirectory.FindSubdirectory("somesubdir");
        FtpDirectory d2 = session.CurrentDirectory.FindSubdirectory("othersubdir");
        session.CurrentDirectory = d2;
        
        /*
         * Following 2 line will cause problem since CurrentDirectory 
         * is not d1's parent anymore
         */
        foreach(FtpDirectory d in d1) 
            //dosomthing

Change current directory

C#
session.CurrentDirectory = somesubdirectory

Upload file

C#
//Blocking call
session.CurrentDirectory.PutFile("somelocalfile");
    
//Async call using callback
session.CurrentDirectory.BeginPutFile("somelocalfile", +
    new FtpAsyncDelegate(yourcallback);
    
//Async call using event
session.EndPutFile += new FtpFileEventHandler(yourhandler);
session.CurrectDirectory.BeginPutFile("somelocalfile");
        
    //Manually upload the file
    FileInfo fi = new FileInfo(localfilefullpath);
    Stream r = File.OpenRead(fi.FullName);

    // actually will return a FtpOutputDataStream object
    Stream w = session.CurrentDirectory.CreateDataStream(fi.Name); 
    int readed;
    byte[] buff = new byte[4096];
    while((readed=r.Read(buff, 0, 4096) != 0)
	    w.Write(buff, 0, readed);
    /*
    * Must call FtpDataStream.Close().
    * This is because it will try to read the file transfer 
    * result from FTP server.
    */
    w.Close();
    s.Close();

Download file

C#
//Blocking call
session.CurrentDirectory.GetFile("someremotefile");
    
//Async call using callback
session.CurrentDirectory.BeginGetFile("someremotefile", + 
    new FtpAsyncDelegate(yourcallback);
    
//Async call using event
session.EngGetFile += new FtpFileEventHandler(yourhandler);
session.CurrectDirectory.BeginGetFile("someremotefile");

//Manually download a file
Stream r = File.OpenWrite(localfilepath);

    FtpFile remoteFile = session.CurrentDirectory.FindFile(remotefilename);
    Stream w = remoteFile.GetOutputDataStream();
    int readed;
    byte[] buff = new byte[4096];
    while((readed=r.Read(buff, 0, 4096) != 0)
        w.Write(buff, 0, readed);
    /*
    * Must call FtpDataStream.Close().
    * This is because it will try to read the file transfer 
    * result from FTP server.
    */
    w.Close();
    s.Close();

Create a new file in ftp server

C#
//method 1
session.CurrentDirectory.CreateFile(newfilename);
        
//method 2
Stream s = session.CurrentDirectory.CreateFileStream(newfilename);
// do something with s
s.Close();

Delete a file from ftp server

C#
//method 1
session.CurrentDirectory.RemoveFile(remotefilename);
        
//method 2
IFtpItem item = session.CurrentDirectory.FindItem(remotefilename)
if(item != null)
    session.CurrentDirectory.RemoveItem(item);

Delete a subdirectory

C#
//method 1
session.CurrentDirectory.RemoveSubdir(subdirectoryname);

//method 2
IFtpItem item = session.CurrentDirectory.FindItem(sub directoryname)
if(item != null)
    session.CurrentDirectory.RemoveItem(item);

Refresh the content of ftp directory

C#
/*
* If you have saved down some some directory item(subdir or ftpfile).
* They will become invalid after you refresh the directory
*/
FtpFile f = session.CurrentDirectory.FindFile(somefile);
         
// you can not leagally use f anymore after the following line
session.CurrentDirectory.Refresh();

Rename a file or directory

C#
IFtpItem item = session.FindItem(directoryorfile);
if(item != null)
    session.RenameSubitem(item, newname);

Known Limitations

  • No support for active mode
  • No support for proxy server

Updates

  • Removed FileCollection and DirectoryCollection
  • Added support for VB's for each statement
  • VB client can directly access FtpDirectory.Files and FtpDirectory.SubDirectories with for each statement now.

Please send me a email if you find any bugs. Please include at least a description of the bug you have found. It will be nice if a testing program or even a solution is included.

Have fun.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Hong Kong Hong Kong
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralSubdirectory Pin
nmbvc2-Mar-06 5:01
nmbvc2-Mar-06 5:01 
GeneralRe: Subdirectory Pin
therearefartoomanybens13-Dec-09 14:51
therearefartoomanybens13-Dec-09 14:51 
Questioncan't download demo file? Pin
Anonymous6-Oct-05 13:39
Anonymous6-Oct-05 13:39 
GeneralHi Alex Pin
santosh poojari14-Sep-05 20:40
santosh poojari14-Sep-05 20:40 
GeneralHelp!! Problem Kcommon GetFile Pin
Member 219735322-Aug-05 21:07
Member 219735322-Aug-05 21:07 
GeneralRe: Help!! Problem Kcommon GetFile Pin
Anonymous29-Aug-05 0:58
Anonymous29-Aug-05 0:58 
Generalavoid blocking while reading response stream! Pin
[pascal]17-Aug-05 4:59
[pascal]17-Aug-05 4:59 
GeneralRe: avoid blocking while reading response stream! Pin
cphexad13-Feb-07 3:44
cphexad13-Feb-07 3:44 
In fact this problem occurs fairly frequently. It is a race condition that happens when the server outputs two responses directly after each other. This happens especially often with the list command, where the server outputs the list, and then the "OK" message.

Because of the way the stream reader works, it reads ahead in the stream. When you call the constructor for the FTPResponse, you create a new stream reader, and thus discards the old one. This is a serious problem since the previous stream reader has already buffered the data. The new stream reader will block forever, since there is no more data.

The solution is to use just one stream reader, and pass that to the FTPResponse constructor.

Another bug in the FTPResponse reader, is that it cannot parse multiline responses:

220 OK - Features:
MDTM
XFR
220-OK

It will try to parse the number in each line, and throw an exception when parsing line 2. It is a fairly small fix. Other than that, actually a really nice component.
GeneralHi Help needed Pin
NR_gopal3-Aug-05 1:40
NR_gopal3-Aug-05 1:40 
Generalunhandled exceptions Pin
[pascal]27-Jul-05 6:24
[pascal]27-Jul-05 6:24 
Generalpatch for linux ftp list parsing Pin
[pascal]25-Jul-05 5:57
[pascal]25-Jul-05 5:57 
GeneralRe: patch for linux ftp list parsing Pin
cwetzelberger8-May-07 4:41
cwetzelberger8-May-07 4:41 
Generaluploading images to ftp using files Pin
v.venkannababu4-Jun-05 23:44
v.venkannababu4-Jun-05 23:44 
Generaldoesnt compile Pin
David Every3-Jun-05 12:20
David Every3-Jun-05 12:20 
QuestionHow to use this coding in ASP.NET ?? Pin
SSISSI16-May-05 18:54
SSISSI16-May-05 18:54 
GeneralUnix Regular Expression Pin
SasquatP29-Mar-05 9:34
SasquatP29-Mar-05 9:34 
GeneralVPN performance problem-design flaw Pin
fmoldoveanu21-Mar-05 13:28
fmoldoveanu21-Mar-05 13:28 
QuestionMultipel-files? Pin
Anonymous24-Feb-05 3:13
Anonymous24-Feb-05 3:13 
GeneralIncomplete download Pin
Anonymous2-Feb-05 12:18
Anonymous2-Feb-05 12:18 
GeneralTypo in kcommon FTP class Pin
Wyatt Wong31-Jan-05 14:44
Wyatt Wong31-Jan-05 14:44 
Generalproxy server support Pin
John Makin6-Jan-05 2:12
John Makin6-Jan-05 2:12 
GeneralAnother free, open-source .NET FTP component Pin
h_c_a_andersen11-Nov-04 11:45
h_c_a_andersen11-Nov-04 11:45 
GeneralRe: Another free, open-source .NET FTP component Pin
[pascal]27-Jul-05 6:17
[pascal]27-Jul-05 6:17 
GeneralcAse-sEnSItiVe regular expressions Match Pin
ttocek8-Nov-04 9:50
ttocek8-Nov-04 9:50 
Generalrequired windows application for uploading last modified files/folders from [Windows] to [WEB] Pin
sharad_sharma_2k25-Sep-04 3:22
sharad_sharma_2k25-Sep-04 3:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.