using System; using System.Net; using System.IO; using System.Text; using System.Net.Sockets; using System.Collections; namespace ftp ...{ publicclass FTP ...{ static ArrayList ar =new ArrayList();
//对于每一个remotehost,该方法广度优先便利ftp站点的所有文件及文件夹 publicstaticvoid GetFileListByHost(string HostName, string UserName, string Password) ...{ FTPclient ftp =new FTPclient(HostName, UserName, Password); FTPdirectory fd = ftp.ListDirectoryDetail("/"); for (int i =0; i < fd.Count; i++) ...{ Console.WriteLine(fd[i].Filename +""+ fd[i].Size); if (fd[i].FileType == FTPfileInfo.DirectoryEntryTypes.Directory) ...{ if (fd[i].NameOnly !=""&& fd[i].NameOnly !="."&& fd[i].NameOnly !="..") ar.Add(fd[i]); } } while (ar.Count >0) ...{ try ...{ fd = ftp.ListDirectoryDetail(((FTPfileInfo)ar[0]).FullName +"/"); for (int i =0; i < fd.Count; i++) ...{ Console.WriteLine(fd[i].Filename +""+ fd[i].Size);//将该句代码换成写进数据库的代码就OK if (fd[i].FileType == FTPfileInfo.DirectoryEntryTypes.Directory) ...{ if (fd[i].NameOnly !=""&& fd[i].NameOnly !="."&& fd[i].NameOnly !="..") ar.Add(fd[i]); } } } catch ...{ continue; } finally ...{ ar.RemoveAt(0); } } } } }
FtpClint类
using System.Diagnostics; using System.Data; using System.Collections; using Microsoft.VisualBasic; using System.Collections.Generic; using System; using System.Net; using System.IO; using System.Text.RegularExpressions; namespace ftp ...{ "FTP client class"#region "FTP client class" /**////<summary> /// A wrapper class for .NET 2.0 FTP ///</summary> ///<remarks> /// This class does not hold open an FTP connection but /// instead is stateless: for each FTP request it /// connects, performs the request and disconnects. ///</remarks> publicclass FTPclient ...{ "CONSTRUCTORS"#region "CONSTRUCTORS" /**////<summary> /// Blank constructor ///</summary> ///<remarks>Hostname, username and password must be set manually</remarks> public FTPclient() ...{ } /**////<summary> /// Constructor just taking the hostname ///</summary> ///<param name="Hostname">in either ftp://ftp.host.com or ftp.host.com form</param> ///<remarks></remarks> public FTPclient(string Hostname) ...{ _hostname = Hostname; } /**////<summary> /// Constructor taking hostname, username and password ///</summary> ///<param name="Hostname">in either ftp://ftp.host.com or ftp.host.com form</param> ///<param name="Username">Leave blank to use 'anonymous' but set password to your email</param> ///<param name="Password"></param> ///<remarks></remarks> public FTPclient(string Hostname, string Username, string Password) ...{ _hostname = Hostname; _username = Username; _password = Password; } #endregion "Directory functions"#region "Directory functions" /**////<summary> /// Return a simple directory listing ///</summary> ///<param name="directory">Directory to list, e.g. /pub</param> ///<returns>A list of filenames and directories as a List(of String)</returns> ///<remarks>For a detailed directory listing, use ListDirectoryDetail</remarks> public List<string> ListDirectory(string directory) ...{ //return a simple list of filenames in directory System.Net.FtpWebRequest ftp = GetRequest(GetDirectory(directory)); //Set request to do simple list ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectory; string str = GetStringResponse(ftp); //replace CRLF to CR, remove last instance str = str.Replace("", "").TrimEnd(''); //split the string into a list List<string> result =new List<string>(); result.AddRange(str.Split('')); return result; } /**////<summary> /// Return a detailed directory listing ///</summary> ///<param name="directory">Directory to list, e.g. /pub/etc</param> ///<returns>An FTPDirectory object</returns> public FTPdirectory ListDirectoryDetail(string directory) ...{ System.Net.FtpWebRequest ftp = GetRequest(GetDirectory(directory)); //Set request to do simple list ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails; string str = GetStringResponse(ftp); //replace CRLF to CR, remove last instance str = str.Replace("", "").TrimEnd(''); //split the string into a list returnnew FTPdirectory(str, _lastDirectory); } #endregion "private supporting fns"#region "private supporting fns" //Get the basic FtpWebRequest object with the //common settings and security private FtpWebRequest GetRequest(string URI) ...{ //create request FtpWebRequest result = (FtpWebRequest)FtpWebRequest.Create(URI); //Set the login details result.Credentials = GetCredentials(); //Do not keep alive (stateless mode) result.KeepAlive =false; return result; } /**////<summary> /// Get the credentials from username/password ///</summary> private System.Net.ICredentials GetCredentials() ...{ returnnew System.Net.NetworkCredential(Username, Password); } /**////<summary> /// returns a full path using CurrentDirectory for a relative file reference ///</summary> privatestring GetFullPath(string file) ...{ if (file.Contains("/")) ...{ return AdjustDir(file); } else ...{ returnthis.CurrentDirectory + file; } } /**////<summary> /// Amend an FTP path so that it always starts with / ///</summary> ///<param name="path">Path to adjust</param> ///<returns></returns> ///<remarks></remarks> privatestring AdjustDir(string path) ...{ return ((path.StartsWith("/")) ?"" : "/").ToString() + path; } privatestring GetDirectory(string directory) ...{ string URI; if (directory =="") ...{ //build from current URI = Hostname +this.CurrentDirectory; _lastDirectory =this.CurrentDirectory; } else ...{ if (!directory.StartsWith("/")) ...{ throw (new ApplicationException("Directory should start with /")); } URI =this.Hostname + directory; _lastDirectory = directory; } return URI; } //stores last retrieved/set directory privatestring _lastDirectory =""; /**////<summary> /// Obtains a response stream as a string ///</summary> ///<param name="ftp">current FTP request</param> ///<returns>String containing response</returns> ///<remarks>FTP servers typically return strings with CR and /// not CRLF. Use respons.Replace(vbCR, vbCRLF) to convert /// to an MSDOS string</remarks> privatestring GetStringResponse(FtpWebRequest ftp) ...{ //Get the result, streaming to a string string result =""; using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse()) ...{ long size = response.ContentLength; using (Stream datastream = response.GetResponseStream()) ...{ using (StreamReader sr =new StreamReader(datastream, System.Text.Encoding.Default)) ...{ result = sr.ReadToEnd(); sr.Close(); } datastream.Close(); } response.Close(); } return result; } /**////<summary> /// Gets the size of an FTP request ///</summary> ///<param name="ftp"></param> ///<returns></returns> ///<remarks></remarks> privatelong GetSize(FtpWebRequest ftp) ...{ long size; using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse()) ...{ size = response.ContentLength; response.Close(); } return size; } #endregion "Properties"#region "Properties" privatestring _hostname; /**////<summary> /// Hostname ///</summary> ///<value></value> ///<remarks>Hostname can be in either the full URL format /// ftp://ftp.myhost.com or just ftp.myhost.com ///</remarks> publicstring Hostname ...{ get ...{ if (_hostname.StartsWith("ftp://")) ...{ return _hostname; } else ...{ return"ftp://"+ _hostname; } } set ...{ _hostname = value; } } privatestring _username; /**////<summary> /// Username property ///</summary> ///<value></value> ///<remarks>Can be left blank, in which case 'anonymous' is returned</remarks> publicstring Username ...{ get ...{ return (_username ==""?"anonymous" : _username); } set ...{ _username = value; } } privatestring _password; publicstring Password ...{ get ...{ return _password; } set ...{ _password = value; } } /**////<summary> /// The CurrentDirectory value ///</summary> ///<remarks>Defaults to the root '/'</remarks> privatestring _currentDirectory ="/"; publicstring CurrentDirectory ...{ get ...{ //return directory, ensure it ends with / return _currentDirectory + ((_currentDirectory.EndsWith("/")) ?"" : "/").ToString(); } set ...{ if (!value.StartsWith("/")) ...{ throw (new ApplicationException("Directory should start with /")); } _currentDirectory = value; } } #endregion } #endregion "FTP file info class"#region "FTP file info class" /**////<summary> /// Represents a file or directory entry from an FTP listing ///</summary> ///<remarks> /// This class is used to parse the results from a detailed /// directory list from FTP. It supports most formats of ///</remarks> publicclass FTPfileInfo ...{ //Stores extended info about FTP file "Properties"#region "Properties" publicstring FullName ...{ get ...{ return Path + Filename; } } publicstring Filename ...{ get ...{ return _filename; } } publicstring Path ...{ get ...{ return _path; } } public DirectoryEntryTypes FileType ...{ get ...{ return _fileType; } } publiclong Size ...{ get ...{ return _size; } } public DateTime FileDateTime ...{ get ...{ return _fileDateTime; } } publicstring Permission ...{ get ...{ return _permission; } } publicstring Extension ...{ get ...{ int i =this.Filename.LastIndexOf("."); if (i >=0&& i <(this.Filename.Length -1)) ...{ returnthis.Filename.Substring(i +1); } else ...{ return""; } } } publicstring NameOnly ...{ get ...{ int i =this.Filename.LastIndexOf("."); if (i >0) ...{ returnthis.Filename.Substring(0, i); } else ...{ returnthis.Filename; } } } privatestring _filename; privatestring _path; private DirectoryEntryTypes _fileType; privatelong _size; private DateTime _fileDateTime; privatestring _permission; #endregion /**////<summary> /// Identifies entry as either File or Directory ///</summary> publicenum DirectoryEntryTypes ...{ File, Directory } /**////<summary> /// Constructor taking a directory listing line and path ///</summary> ///<param name="line">The line returned from the detailed directory list</param> ///<param name="path">Path of the directory</param> ///<remarks></remarks> public FTPfileInfo(string line, string path) ...{ //parse line Match m = GetMatchingRegex(line); if (m ==null) ...{ //failed throw (new ApplicationException("Unable to parse line: "+ line)); } else ...{ _filename = m.Groups["name"].Value; _path = path; Int64.TryParse(m.Groups["size"].Value, out _size); //_size = System.Convert.ToInt32(m.Groups["size"].Value); _permission = m.Groups["permission"].Value; string _dir = m.Groups["dir"].Value; if (_dir !=""&& _dir !="-") ...{ _fileType = DirectoryEntryTypes.Directory; } else ...{ _fileType = DirectoryEntryTypes.File; } try ...{ _fileDateTime = DateTime.Parse(m.Groups["timestamp"].Value); } catch (Exception) ...{ _fileDateTime = Convert.ToDateTime(null); } } } private Match GetMatchingRegex(string line) ...{ Regex rx; Match m; for (int i =0; i <= _ParseFormats.Length -1; i++) ...{ rx =new Regex(_ParseFormats[i]); m = rx.Match(line); if (m.Success) ...{ return m; } } returnnull; } "Regular expressions for parsing LIST results"#region "Regular expressions for parsing LIST results" /**////<summary> /// List of REGEX formats for different FTP server listing formats ///</summary> ///<remarks> /// The first three are various UNIX/LINUX formats, fourth is for MS FTP /// in detailed mode and the last for MS FTP in 'DOS' mode. /// I wish VB.NET had support for Const arrays like C# but there you go ///</remarks> privatestaticstring[] _ParseFormats =newstring[] ...{ "(?<dir>[/-d])(?<permission>([/-r][/-w][/-xs]){3})/s+/d+/s+/w+/s+/w+/s+(?<size>/d+)/s+(?<timestamp>/w+/s+/d+/s+/d{4})/s+(?<name>.+)", "(?<dir>[/-d])(?<permission>([/-r][/-w][/-xs]){3})/s+/d+/s+/d+/s+(?<size>/d+)/s+(?<timestamp>/w+/s+/d+/s+/d{4})/s+(?<name>.+)", "(?<dir>[/-d])(?<permission>([/-r][/-w][/-xs]){3})/s+/d+/s+/d+/s+(?<size>/d+)/s+(?<timestamp>/w+/s+/d+/s+/d{1,2}:/d{2})/s+(?<name>.+)", "(?<dir>[/-d])(?<permission>([/-r][/-w][/-xs]){3})/s+/d+/s+/w+/s+/w+/s+(?<size>/d+)/s+(?<timestamp>/w+/s+/d+/s+/d{1,2}:/d{2})/s+(?<name>.+)", "(?<dir>[/-d])(?<permission>([/-r][/-w][/-xs]){3})(/s+)(?<size>(/d+))(/s+)(?<ctbit>(/w+/s/w+))(/s+)(?<size2>(/d+))/s+(?<timestamp>/w+/s+/d+/s+/d{2}:/d{2})/s+(?<name>.+)", "(?<timestamp>/d{2}/-/d{2}/-/d{2}/s+/d{2}:/d{2}[Aa|Pp][mM])/s+(?<dir>/</w+/>){0,1}(?<size>/d+){0,1}/s+(?<name>.+)" }; #endregion } #endregion "FTP Directory class"#region "FTP Directory class" /**////<summary> /// Stores a list of files and directories from an FTP result ///</summary> ///<remarks></remarks> publicclass FTPdirectory : List<FTPfileInfo> ...{ public FTPdirectory() ...{ //creates a blank directory listing } /**////<summary> /// Constructor: create list from a (detailed) directory string ///</summary> ///<param name="dir">directory listing string</param> ///<param name="path"></param> ///<remarks></remarks> public FTPdirectory(string dir, string path) ...{ foreach (string line in dir.Replace("", "").Split(System.Convert.ToChar(''))) ...{ //parse if (line !="") ...{ try ...{ this.Add(new FTPfileInfo(line, path)); } catch ...{ continue; } } } } /**////<summary> /// Filter out only files from directory listing ///</summary> ///<param name="ext">optional file extension filter</param> ///<returns>FTPdirectory listing</returns> public FTPdirectory GetFiles(string ext) ...{ returnthis.GetFileOrDir(FTPfileInfo.DirectoryEntryTypes.File, ext); } /**////<summary> /// Returns a list of only subdirectories ///</summary> ///<returns>FTPDirectory list</returns> ///<remarks></remarks> public FTPdirectory GetDirectories() ...{ returnthis.GetFileOrDir(FTPfileInfo.DirectoryEntryTypes.Directory, ""); } //internal: share use function for GetDirectories/Files private FTPdirectory GetFileOrDir(FTPfileInfo.DirectoryEntryTypes type, string ext) ...{ FTPdirectory result =new FTPdirectory(); foreach (FTPfileInfo fi inthis) ...{ if (fi.FileType == type) ...{ if (ext =="") ...{ result.Add(fi); } elseif (ext == fi.Extension) ...{ result.Add(fi); } } } return result; } publicbool FileExists(string filename) ...{ foreach (FTPfileInfo ftpfile inthis) ...{ if (ftpfile.Filename == filename) ...{ returntrue; } } returnfalse; } privateconstchar slash ='/'; publicstaticstring GetParentDirectory(string dir) ...{ string tmp = dir.TrimEnd(slash); int i = tmp.LastIndexOf(slash); if (i >0) ...{ return tmp.Substring(0, i -1); } else ...{ throw (new ApplicationException("No parent for root")); } } } #endregion }