FTP(文件傳輸協議)
FTP 是File Transfer Protocol(文件傳輸協議)的英文簡稱,而中文簡稱為“文傳協議”。用於Internet上的控制文件的雙向傳輸。同時,它也是一個應用程序(Application)。基於不同的操作系統有不同的FTP應用程序,而所有這些應用程序都遵守同一種協議以傳輸文件。在FTP的使用當中,用戶經常遇到兩個概念:"下載"(Download)和"上傳"(Upload)。"下載"文件就是從遠程主機拷貝文件至自己的計算機上;"上傳"文件就是將文件從自己的計算機中拷貝至遠程主機上。用Internet語言來說,用戶可通過客戶機程序向(從)遠程主機上傳(下載)文件。
運行機制
FTP服務器
簡單地說,支持FTP協議的服務器就是FTP服務器。
與大多數Internet服務一樣,FTP也是一個客戶機/服務器系統。用戶通過一個支持FTP協議的客戶機程序,連接到在遠程主機上的FTP服務器程序。用戶通過客戶機程序向服務器程序發出命令,服務器程序執行用戶所發出的命令,並將執行的結果返回到客戶機。比如說,用戶發出一條命令,要求服務器向用戶傳送某一個文件的一份拷貝,服務器會響應這條命令,將指定文件送至用戶的機器上。客戶機程序代表用戶接收到這個文件,將其存放在用戶目錄中。
匿名FTP
使用FTP時必須首先登錄,在遠程主機上獲得相應的權限以后,方可下載或上傳文件。也就是說,要想同哪一台計算機傳送文件,就必須具有哪一台計算機的適當授權。換言之,除非有用戶ID和口令,否則便無法傳送文件。這種情況違背了Internet的開放性,Internet上的FTP主機何止千萬,不可能要求每個用戶在每一台主機上都擁有帳號。匿名FTP就是為解決這個問題而產生的。
匿名FTP是這樣一種機制,用戶可通過它連接到遠程主機上,並從其下載文件,而無需成為其注冊用戶。系統管理員建立了一個特殊的用戶ID,名為anonymous, Internet上的任何人在任何地方都可使用該用戶ID。
通過FTP程序連接匿名FTP主機的方式同連接普通FTP主機的方式差不多,只是在要求提供用戶標識ID時必須輸入anonymous,該用戶ID的口令可以是任意的字符串。習慣上,用自己的E-mail地址作為口令,使系統維護程序能夠記錄下來誰在存取這些文件。
值得注意的是,匿名FTP不適用於所有Internet主機,它只適用於那些提供了這項服務的主機。
當遠程主機提供匿名FTP服務時,會指定某些目錄向公眾開放,允許匿名存取。系統中的其余目錄則處於隱匿狀態。作為一種安全措施,大多數匿名FTP主機都允許用戶從其下載文件,而不允許用戶向其上傳文件,也就是說,用戶可將匿名FTP主機上的所有文件全部拷貝到自己的機器上,但不能將自己機器上的任何一個文件拷貝至匿名FTP主機上。即使有些匿名FTP主機確實允許用戶上傳文件,用戶也只能將文件上傳至某一指定上傳目錄中。隨后,系統管理員會去檢查這些文件,他會將這些文件移至另一個公共下載目錄中,供其他用戶下載,利用這種方式,遠程主機的用戶得到了保護,避免了有人上傳有問題的文件,如帶病毒的文件。
傳輸方式
FTP的傳輸有兩種方式:ASCII、二進制。
ASCII傳輸方式
假定用戶正在拷貝的文件包含的簡單ASCII碼文本,如果在遠程機器上運行的不是UNIX,當文件傳輸時ftp通常會自動地調整文件的內容以便於把文件解釋成另外那台計算機存儲文本文件的格式。
但是常常有這樣的情況,用戶正在傳輸的文件包含的不是文本文件,它們可能是程序,數據庫,字處理文件或者壓縮文件。在拷貝任何非文本文件之前,用binary 命令告訴ftp逐字拷貝。
二進制傳輸模式
在二進制傳輸中,保存文件的位序,以便原始和拷貝的是逐位一一對應的。即使目的地機器上包含位序列的文件是沒意義的。例如,macintosh以二進制方式傳送可執行文件到Windows系統,在對方系統上,此文件不能執行。
如在ASCII方式下傳輸二進制文件,即使不需要也仍會轉譯。這會損壞數據。(ASCII方式一般假設每一字符的第一有效位無意義,因為ASCII字符組合不使用它。如果傳輸二進制文件,所有的位都是重要的。)
FTPHelper操作類方便使用

using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Net; using System.Text.RegularExpressions; namespace DotNet.Dal { public class FTPHelper { #region 字段 string ftpURI; string ftpUserID; string ftpServerIP; string ftpPassword; string ftpRemotePath; #endregion /// <summary> /// 連接FTP服務器 /// </summary> /// <param name="FtpServerIP">FTP連接地址</param> /// <param name="FtpRemotePath">指定FTP連接成功后的當前目錄, 如果不指定即默認為根目錄</param> /// <param name="FtpUserID">用戶名</param> /// <param name="FtpPassword">密碼</param> public FTPHelper(string FtpServerIP, string FtpRemotePath, string FtpUserID, string FtpPassword) { ftpServerIP = FtpServerIP; ftpRemotePath = FtpRemotePath; ftpUserID = FtpUserID; ftpPassword = FtpPassword; ftpURI = "ftp://" + ftpServerIP + "/" + ftpRemotePath + "/"; } /// <summary> /// 上傳 /// </summary> public void Upload(string filename) { FileInfo fileInf = new FileInfo(filename); FtpWebRequest reqFTP; reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + fileInf.Name)); reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.Method = WebRequestMethods.Ftp.UploadFile; reqFTP.KeepAlive = false; reqFTP.UseBinary = true; reqFTP.ContentLength = fileInf.Length; int buffLength = 2048; byte[] buff = new byte[buffLength]; int contentLen; FileStream fs = fileInf.OpenRead(); try { Stream strm = reqFTP.GetRequestStream(); contentLen = fs.Read(buff, 0, buffLength); while (contentLen != 0) { strm.Write(buff, 0, contentLen); contentLen = fs.Read(buff, 0, buffLength); } strm.Close(); fs.Close(); } catch (Exception ex) { throw new Exception(ex.Message); } } /// <summary> /// 下載 /// </summary> public void Download(string filePath, string fileName) { try { FileStream outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create); FtpWebRequest reqFTP; reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + fileName)); reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.Method = WebRequestMethods.Ftp.DownloadFile; reqFTP.UseBinary = true; 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) { throw new Exception(ex.Message); } } /// <summary> /// 刪除文件 /// </summary> public void Delete(string fileName) { try { FtpWebRequest reqFTP; reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + fileName)); reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.Method = WebRequestMethods.Ftp.DeleteFile; reqFTP.KeepAlive = false; string result = String.Empty; FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); long size = response.ContentLength; Stream datastream = response.GetResponseStream(); StreamReader sr = new StreamReader(datastream); result = sr.ReadToEnd(); sr.Close(); datastream.Close(); response.Close(); } catch (Exception ex) { throw new Exception(ex.Message); } } /// <summary> /// 獲取當前目錄下明細(包含文件和文件夾) /// </summary> public string[] GetFilesDetailList() { try { StringBuilder result = new StringBuilder(); FtpWebRequest ftp; ftp = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI)); ftp.Credentials = new NetworkCredential(ftpUserID, ftpPassword); ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails; WebResponse response = ftp.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); string line = reader.ReadLine(); line = reader.ReadLine(); line = reader.ReadLine(); while (line != null) { result.Append(line); result.Append("\n"); line = reader.ReadLine(); } result.Remove(result.ToString().LastIndexOf("\n"), 1); reader.Close(); response.Close(); return result.ToString().Split('\n'); } catch (Exception ex) { throw new Exception(ex.Message); } } /// <summary> /// 獲取FTP文件列表(包括文件夾) /// </summary> private string[] GetAllList(string url) { List<string> list = new List<string>(); FtpWebRequest req = (FtpWebRequest)WebRequest.Create(new Uri(url)); req.Credentials = new NetworkCredential(ftpPassword, ftpPassword); req.Method = WebRequestMethods.Ftp.ListDirectory; req.UseBinary = true; req.UsePassive = true; try { using (FtpWebResponse res = (FtpWebResponse)req.GetResponse()) { using (StreamReader sr = new StreamReader(res.GetResponseStream())) { string s; while ((s = sr.ReadLine()) != null) { list.Add(s); } } } } catch (Exception ex) { throw (ex); } return list.ToArray(); } /// <summary> /// 獲取當前目錄下文件列表(不包括文件夾) /// </summary> public string[] GetFileList(string url) { StringBuilder result = new StringBuilder(); FtpWebRequest reqFTP; try { reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(url)); reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpPassword, ftpPassword); reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails; WebResponse response = reqFTP.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); string line = reader.ReadLine(); while (line != null) { if (line.IndexOf("<DIR>") == -1) { result.Append(Regex.Match(line, @"[\S]+ [\S]+", RegexOptions.IgnoreCase).Value.Split(' ')[1]); result.Append("\n"); } line = reader.ReadLine(); } result.Remove(result.ToString().LastIndexOf('\n'), 1); reader.Close(); response.Close(); } catch (Exception ex) { throw (ex); } return result.ToString().Split('\n'); } /// <summary> /// 判斷當前目錄下指定的文件是否存在 /// </summary> /// <param name="RemoteFileName">遠程文件名</param> public bool FileExist(string RemoteFileName) { string[] fileList = GetFileList("*.*"); foreach (string str in fileList) { if (str.Trim() == RemoteFileName.Trim()) { return true; } } return false; } /// <summary> /// 創建文件夾 /// </summary> public void MakeDir(string dirName) { FtpWebRequest reqFTP; try { reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + dirName)); reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory; reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); Stream ftpStream = response.GetResponseStream(); ftpStream.Close(); response.Close(); } catch (Exception ex) { } } /// <summary> /// 獲取指定文件大小 /// </summary> public long GetFileSize(string filename) { FtpWebRequest reqFTP; long fileSize = 0; try { reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + filename)); reqFTP.Method = WebRequestMethods.Ftp.GetFileSize; reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); Stream ftpStream = response.GetResponseStream(); fileSize = response.ContentLength; ftpStream.Close(); response.Close(); } catch (Exception ex) { } return fileSize; } /// <summary> /// 更改文件名 /// </summary> public void ReName(string currentFilename, string newFilename) { FtpWebRequest reqFTP; try { reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + currentFilename)); reqFTP.Method = WebRequestMethods.Ftp.Rename; reqFTP.RenameTo = newFilename; reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); Stream ftpStream = response.GetResponseStream(); ftpStream.Close(); response.Close(); } catch (Exception ex) { } } /// <summary> /// 移動文件 /// </summary> public void MovieFile(string currentFilename, string newDirectory) { ReName(currentFilename, newDirectory); } /// <summary> /// 切換當前目錄 /// </summary> /// <param name="IsRoot">true:絕對路徑 false:相對路徑</param> public void GotoDirectory(string DirectoryName, bool IsRoot) { if (IsRoot) { ftpRemotePath = DirectoryName; } else { ftpRemotePath += DirectoryName + "/"; } ftpURI = "ftp://" + ftpServerIP + "/" + ftpRemotePath + "/"; } } }

using System; using System.Text; using System.IO; namespace DotNet.Dal { public class FTPOperater { #region 屬性 private FTPClient ftp; /// <summary> /// 全局FTP訪問變量 /// </summary> public FTPClient Ftp { get { return ftp; } set { ftp = value; } } private string _server; /// <summary> /// Ftp服務器 /// </summary> public string Server { get { return _server; } set { _server = value; } } private string _User; /// <summary> /// Ftp用戶 /// </summary> public string User { get { return _User; } set { _User = value; } } private string _Pass; /// <summary> /// Ftp密碼 /// </summary> public string Pass { get { return _Pass; } set { _Pass = value; } } private string _FolderZJ; /// <summary> /// Ftp密碼 /// </summary> public string FolderZJ { get { return _FolderZJ; } set { _FolderZJ = value; } } private string _FolderWX; /// <summary> /// Ftp密碼 /// </summary> public string FolderWX { get { return _FolderWX; } set { _FolderWX = value; } } #endregion /// <summary> /// 得到文件列表 /// </summary> /// <returns></returns> public string[] GetList(string strPath) { if (ftp == null) ftp = this.getFtpClient(); ftp.Connect(); ftp.ChDir(strPath); return ftp.Dir("*"); } /// <summary> /// 下載文件 /// </summary> /// <param name="ftpFolder">ftp目錄</param> /// <param name="ftpFileName">ftp文件名</param> /// <param name="localFolder">本地目錄</param> /// <param name="localFileName">本地文件名</param> public bool GetFile(string ftpFolder, string ftpFileName, string localFolder, string localFileName) { try { if (ftp == null) ftp = this.getFtpClient(); if (!ftp.Connected) { ftp.Connect(); ftp.ChDir(ftpFolder); } ftp.Get(ftpFileName, localFolder, localFileName); return true; } catch { try { ftp.DisConnect(); ftp = null; } catch { ftp = null; } return false; } } /// <summary> /// 修改文件 /// </summary> /// <param name="ftpFolder">本地目錄</param> /// <param name="ftpFileName">本地文件名temp</param> /// <param name="localFolder">本地目錄</param> /// <param name="localFileName">本地文件名</param> public bool AddMSCFile(string ftpFolder, string ftpFileName, string localFolder, string localFileName, string BscInfo) { string sLine = ""; string sResult = ""; string path = "獲得應用程序所在的完整的路徑"; path = path.Substring(0, path.LastIndexOf("\\")); try { FileStream fsFile = new FileStream(ftpFolder + "\\" + ftpFileName, FileMode.Open); FileStream fsFileWrite = new FileStream(localFolder + "\\" + localFileName, FileMode.Create); StreamReader sr = new StreamReader(fsFile); StreamWriter sw = new StreamWriter(fsFileWrite); sr.BaseStream.Seek(0, SeekOrigin.Begin); while (sr.Peek() > -1) { sLine = sr.ReadToEnd(); } string[] arStr = sLine.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < arStr.Length - 1; i++) { sResult += BscInfo + "," + arStr[i].Trim() + "\n"; } sr.Close(); byte[] connect = new UTF8Encoding(true).GetBytes(sResult); fsFileWrite.Write(connect, 0, connect.Length); fsFileWrite.Flush(); sw.Close(); fsFile.Close(); fsFileWrite.Close(); return true; } catch (Exception e) { return false; } } /// <summary> /// 刪除文件 /// </summary> /// <param name="ftpFolder">ftp目錄</param> /// <param name="ftpFileName">ftp文件名</param> public bool DelFile(string ftpFolder, string ftpFileName) { try { if (ftp == null) ftp = this.getFtpClient(); if (!ftp.Connected) { ftp.Connect(); ftp.ChDir(ftpFolder); } ftp.Delete(ftpFileName); return true; } catch { return false; } } /// <summary> /// 上傳文件 /// </summary> /// <param name="ftpFolder">ftp目錄</param> /// <param name="ftpFileName">ftp文件名</param> public bool PutFile(string ftpFolder, string ftpFileName) { try { if (ftp == null) ftp = this.getFtpClient(); if (!ftp.Connected) { ftp.Connect(); ftp.ChDir(ftpFolder); } ftp.Put(ftpFileName); return true; } catch { return false; } } /// <summary> /// 下載文件 /// </summary> /// <param name="ftpFolder">ftp目錄</param> /// <param name="ftpFileName">ftp文件名</param> /// <param name="localFolder">本地目錄</param> /// <param name="localFileName">本地文件名</param> public bool GetFileNoBinary(string ftpFolder, string ftpFileName, string localFolder, string localFileName) { try { if (ftp == null) ftp = this.getFtpClient(); if (!ftp.Connected) { ftp.Connect(); ftp.ChDir(ftpFolder); } ftp.GetNoBinary(ftpFileName, localFolder, localFileName); return true; } catch { try { ftp.DisConnect(); ftp = null; } catch { ftp = null; } return false; } } /// <summary> /// 得到FTP上文件信息 /// </summary> /// <param name="ftpFolder">FTP目錄</param> /// <param name="ftpFileName">ftp文件名</param> public string GetFileInfo(string ftpFolder, string ftpFileName) { string strResult = ""; try { if (ftp == null) ftp = this.getFtpClient(); if (ftp.Connected) ftp.DisConnect(); ftp.Connect(); ftp.ChDir(ftpFolder); strResult = ftp.GetFileInfo(ftpFileName); return strResult; } catch { return ""; } } /// <summary> /// 測試FTP服務器是否可登陸 /// </summary> public bool CanConnect() { if (ftp == null) ftp = this.getFtpClient(); try { ftp.Connect(); ftp.DisConnect(); return true; } catch { return false; } } /// <summary> /// 得到FTP上文件信息 /// </summary> /// <param name="ftpFolder">FTP目錄</param> /// <param name="ftpFileName">ftp文件名</param> public string GetFileInfoConnected(string ftpFolder, string ftpFileName) { string strResult = ""; try { if (ftp == null) ftp = this.getFtpClient(); if (!ftp.Connected) { ftp.Connect(); ftp.ChDir(ftpFolder); } strResult = ftp.GetFileInfo(ftpFileName); return strResult; } catch { return ""; } } /// <summary> /// 得到文件列表 /// </summary> /// <param name="ftpFolder">FTP目錄</param> /// <returns>FTP通配符號</returns> public string[] GetFileList(string ftpFolder, string strMask) { string[] strResult; try { if (ftp == null) ftp = this.getFtpClient(); if (!ftp.Connected) { ftp.Connect(); ftp.ChDir(ftpFolder); } strResult = ftp.Dir(strMask); return strResult; } catch { return null; } } /// <summary> ///得到FTP傳輸對象 /// </summary> public FTPClient getFtpClient() { FTPClient ft = new FTPClient(); ft.RemoteHost = this.Server; ft.RemoteUser = this.User; ft.RemotePass = this.Pass; return ft; } } }

1 using System; 2 using System.Net; 3 using System.IO; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.Threading; 7 8 namespace DotNet.Dal 9 { 10 public class FTPClient 11 { 12 public static object obj = new object(); 13 14 #region 構造函數 15 /// <summary> 16 /// 缺省構造函數 17 /// </summary> 18 public FTPClient() 19 { 20 strRemoteHost = ""; 21 strRemotePath = ""; 22 strRemoteUser = ""; 23 strRemotePass = ""; 24 strRemotePort = 21; 25 bConnected = false; 26 } 27 28 /// <summary> 29 /// 構造函數 30 /// </summary> 31 public FTPClient(string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort) 32 { 33 strRemoteHost = remoteHost; 34 strRemotePath = remotePath; 35 strRemoteUser = remoteUser; 36 strRemotePass = remotePass; 37 strRemotePort = remotePort; 38 Connect(); 39 } 40 #endregion 41 42 #region 字段 43 private int strRemotePort; 44 private Boolean bConnected; 45 private string strRemoteHost; 46 private string strRemotePass; 47 private string strRemoteUser; 48 private string strRemotePath; 49 50 /// <summary> 51 /// 服務器返回的應答信息(包含應答碼) 52 /// </summary> 53 private string strMsg; 54 /// <summary> 55 /// 服務器返回的應答信息(包含應答碼) 56 /// </summary> 57 private string strReply; 58 /// <summary> 59 /// 服務器返回的應答碼 60 /// </summary> 61 private int iReplyCode; 62 /// <summary> 63 /// 進行控制連接的socket 64 /// </summary> 65 private Socket socketControl; 66 /// <summary> 67 /// 傳輸模式 68 /// </summary> 69 private TransferType trType; 70 /// <summary> 71 /// 接收和發送數據的緩沖區 72 /// </summary> 73 private static int BLOCK_SIZE = 512; 74 /// <summary> 75 /// 編碼方式 76 /// </summary> 77 Encoding ASCII = Encoding.ASCII; 78 /// <summary> 79 /// 字節數組 80 /// </summary> 81 Byte[] buffer = new Byte[BLOCK_SIZE]; 82 #endregion 83 84 #region 屬性 85 /// <summary> 86 /// FTP服務器IP地址 87 /// </summary> 88 public string RemoteHost 89 { 90 get 91 { 92 return strRemoteHost; 93 } 94 set 95 { 96 strRemoteHost = value; 97 } 98 } 99 100 /// <summary> 101 /// FTP服務器端口 102 /// </summary> 103 public int RemotePort 104 { 105 get 106 { 107 return strRemotePort; 108 } 109 set 110 { 111 strRemotePort = value; 112 } 113 } 114 115 /// <summary> 116 /// 當前服務器目錄 117 /// </summary> 118 public string RemotePath 119 { 120 get 121 { 122 return strRemotePath; 123 } 124 set 125 { 126 strRemotePath = value; 127 } 128 } 129 130 /// <summary> 131 /// 登錄用戶賬號 132 /// </summary> 133 public string RemoteUser 134 { 135 set 136 { 137 strRemoteUser = value; 138 } 139 } 140 141 /// <summary> 142 /// 用戶登錄密碼 143 /// </summary> 144 public string RemotePass 145 { 146 set 147 { 148 strRemotePass = value; 149 } 150 } 151 152 /// <summary> 153 /// 是否登錄 154 /// </summary> 155 public bool Connected 156 { 157 get 158 { 159 return bConnected; 160 } 161 } 162 #endregion 163 164 #region 鏈接 165 /// <summary> 166 /// 建立連接 167 /// </summary> 168 public void Connect() 169 { 170 lock (obj) 171 { 172 socketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 173 IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), strRemotePort); 174 try 175 { 176 socketControl.Connect(ep); 177 } 178 catch (Exception) 179 { 180 throw new IOException("不能連接ftp服務器"); 181 } 182 } 183 ReadReply(); 184 if (iReplyCode != 220) 185 { 186 DisConnect(); 187 throw new IOException(strReply.Substring(4)); 188 } 189 SendCommand("USER " + strRemoteUser); 190 if (!(iReplyCode == 331 || iReplyCode == 230)) 191 { 192 CloseSocketConnect(); 193 throw new IOException(strReply.Substring(4)); 194 } 195 if (iReplyCode != 230) 196 { 197 SendCommand("PASS " + strRemotePass); 198 if (!(iReplyCode == 230 || iReplyCode == 202)) 199 { 200 CloseSocketConnect(); 201 throw new IOException(strReply.Substring(4)); 202 } 203 } 204 bConnected = true; 205 ChDir(strRemotePath); 206 } 207 208 /// <summary> 209 /// 關閉連接 210 /// </summary> 211 public void DisConnect() 212 { 213 if (socketControl != null) 214 { 215 SendCommand("QUIT"); 216 } 217 CloseSocketConnect(); 218 } 219 #endregion 220 221 #region 傳輸模式 222 /// <summary> 223 /// 傳輸模式:二進制類型、ASCII類型 224 /// </summary> 225 public enum TransferType { Binary, ASCII }; 226 227 /// <summary> 228 /// 設置傳輸模式 229 /// </summary> 230 /// <param name="ttType">傳輸模式</param> 231 public void SetTransferType(TransferType ttType) 232 { 233 if (ttType == TransferType.Binary) 234 { 235 SendCommand("TYPE I");//binary類型傳輸 236 } 237 else 238 { 239 SendCommand("TYPE A");//ASCII類型傳輸 240 } 241 if (iReplyCode != 200) 242 { 243 throw new IOException(strReply.Substring(4)); 244 } 245 else 246 { 247 trType = ttType; 248 } 249 } 250 251 /// <summary> 252 /// 獲得傳輸模式 253 /// </summary> 254 /// <returns>傳輸模式</returns> 255 public TransferType GetTransferType() 256 { 257 return trType; 258 } 259 #endregion 260 261 #region 文件操作 262 /// <summary> 263 /// 獲得文件列表 264 /// </summary> 265 /// <param name="strMask">文件名的匹配字符串</param> 266 public string[] Dir(string strMask) 267 { 268 if (!bConnected) 269 { 270 Connect(); 271 } 272 Socket socketData = CreateDataSocket(); 273 SendCommand("NLST " + strMask); 274 if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226)) 275 { 276 throw new IOException(strReply.Substring(4)); 277 } 278 strMsg = ""; 279 Thread.Sleep(2000); 280 while (true) 281 { 282 int iBytes = socketData.Receive(buffer, buffer.Length, 0); 283 strMsg += ASCII.GetString(buffer, 0, iBytes); 284 if (iBytes < buffer.Length) 285 { 286 break; 287 } 288 } 289 char[] seperator = { '\n' }; 290 string[] strsFileList = strMsg.Split(seperator); 291 socketData.Close(); //數據socket關閉時也會有返回碼 292 if (iReplyCode != 226) 293 { 294 ReadReply(); 295 if (iReplyCode != 226) 296 { 297 298 throw new IOException(strReply.Substring(4)); 299 } 300 } 301 return strsFileList; 302 } 303 304 public void newPutByGuid(string strFileName, string strGuid) 305 { 306 if (!bConnected) 307 { 308 Connect(); 309 } 310 string str = strFileName.Substring(0, strFileName.LastIndexOf("\\")); 311 string strTypeName = strFileName.Substring(strFileName.LastIndexOf(".")); 312 strGuid = str + "\\" + strGuid; 313 Socket socketData = CreateDataSocket(); 314 SendCommand("STOR " + Path.GetFileName(strGuid)); 315 if (!(iReplyCode == 125 || iReplyCode == 150)) 316 { 317 throw new IOException(strReply.Substring(4)); 318 } 319 FileStream input = new FileStream(strGuid, FileMode.Open); 320 input.Flush(); 321 int iBytes = 0; 322 while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0) 323 { 324 socketData.Send(buffer, iBytes, 0); 325 } 326 input.Close(); 327 if (socketData.Connected) 328 { 329 socketData.Close(); 330 } 331 if (!(iReplyCode == 226 || iReplyCode == 250)) 332 { 333 ReadReply(); 334 if (!(iReplyCode == 226 || iReplyCode == 250)) 335 { 336 throw new IOException(strReply.Substring(4)); 337 } 338 } 339 } 340 341 /// <summary> 342 /// 獲取文件大小 343 /// </summary> 344 /// <param name="strFileName">文件名</param> 345 /// <returns>文件大小</returns> 346 public long GetFileSize(string strFileName) 347 { 348 if (!bConnected) 349 { 350 Connect(); 351 } 352 SendCommand("SIZE " + Path.GetFileName(strFileName)); 353 long lSize = 0; 354 if (iReplyCode == 213) 355 { 356 lSize = Int64.Parse(strReply.Substring(4)); 357 } 358 else 359 { 360 throw new IOException(strReply.Substring(4)); 361 } 362 return lSize; 363 } 364 365 366 /// <summary> 367 /// 獲取文件信息 368 /// </summary> 369 /// <param name="strFileName">文件名</param> 370 /// <returns>文件大小</returns> 371 public string GetFileInfo(string strFileName) 372 { 373 if (!bConnected) 374 { 375 Connect(); 376 } 377 Socket socketData = CreateDataSocket(); 378 SendCommand("LIST " + strFileName); 379 string strResult = ""; 380 if (!(iReplyCode == 150 || iReplyCode == 125 381 || iReplyCode == 226 || iReplyCode == 250)) 382 { 383 throw new IOException(strReply.Substring(4)); 384 } 385 byte[] b = new byte[512]; 386 MemoryStream ms = new MemoryStream(); 387 388 while (true) 389 { 390 int iBytes = socketData.Receive(b, b.Length, 0); 391 ms.Write(b, 0, iBytes); 392 if (iBytes <= 0) 393 { 394 395 break; 396 } 397 } 398 byte[] bt = ms.GetBuffer(); 399 strResult = System.Text.Encoding.ASCII.GetString(bt); 400 ms.Close(); 401 return strResult; 402 } 403 404 /// <summary> 405 /// 刪除 406 /// </summary> 407 /// <param name="strFileName">待刪除文件名</param> 408 public void Delete(string strFileName) 409 { 410 if (!bConnected) 411 { 412 Connect(); 413 } 414 SendCommand("DELE " + strFileName); 415 if (iReplyCode != 250) 416 { 417 throw new IOException(strReply.Substring(4)); 418 } 419 } 420 421 /// <summary> 422 /// 重命名(如果新文件名與已有文件重名,將覆蓋已有文件) 423 /// </summary> 424 /// <param name="strOldFileName">舊文件名</param> 425 /// <param name="strNewFileName">新文件名</param> 426 public void Rename(string strOldFileName, string strNewFileName) 427 { 428 if (!bConnected) 429 { 430 Connect(); 431 } 432 SendCommand("RNFR " + strOldFileName); 433 if (iReplyCode != 350) 434 { 435 throw new IOException(strReply.Substring(4)); 436 } 437 // 如果新文件名與原有文件重名,將覆蓋原有文件 438 SendCommand("RNTO " + strNewFileName); 439 if (iReplyCode != 250) 440 { 441 throw new IOException(strReply.Substring(4)); 442 } 443 } 444 #endregion 445 446 #region 上傳和下載 447 /// <summary> 448 /// 下載一批文件 449 /// </summary> 450 /// <param name="strFileNameMask">文件名的匹配字符串</param> 451 /// <param name="strFolder">本地目錄(不得以\結束)</param> 452 public void Get(string strFileNameMask, string strFolder) 453 { 454 if (!bConnected) 455 { 456 Connect(); 457 } 458 string[] strFiles = Dir(strFileNameMask); 459 foreach (string strFile in strFiles) 460 { 461 if (!strFile.Equals(""))//一般來說strFiles的最后一個元素可能是空字符串 462 { 463 Get(strFile, strFolder, strFile); 464 } 465 } 466 } 467 468 /// <summary> 469 /// 下載一個文件 470 /// </summary> 471 /// <param name="strRemoteFileName">要下載的文件名</param> 472 /// <param name="strFolder">本地目錄(不得以\結束)</param> 473 /// <param name="strLocalFileName">保存在本地時的文件名</param> 474 public void Get(string strRemoteFileName, string strFolder, string strLocalFileName) 475 { 476 Socket socketData = CreateDataSocket(); 477 try 478 { 479 if (!bConnected) 480 { 481 Connect(); 482 } 483 SetTransferType(TransferType.Binary); 484 if (strLocalFileName.Equals("")) 485 { 486 strLocalFileName = strRemoteFileName; 487 } 488 SendCommand("RETR " + strRemoteFileName); 489 if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226 || iReplyCode == 250)) 490 { 491 throw new IOException(strReply.Substring(4)); 492 } 493 FileStream output = new FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create); 494 while (true) 495 { 496 int iBytes = socketData.Receive(buffer, buffer.Length, 0); 497 output.Write(buffer, 0, iBytes); 498 if (iBytes <= 0) 499 { 500 break; 501 } 502 } 503 output.Close(); 504 if (socketData.Connected) 505 { 506 socketData.Close(); 507 } 508 if (!(iReplyCode == 226 || iReplyCode == 250)) 509 { 510 ReadReply(); 511 if (!(iReplyCode == 226 || iReplyCode == 250)) 512 { 513 throw new IOException(strReply.Substring(4)); 514 } 515 } 516 } 517 catch 518 { 519 socketData.Close(); 520 socketData = null; 521 socketControl.Close(); 522 bConnected = false; 523 socketControl = null; 524 } 525 } 526 527 /// <summary> 528 /// 下載一個文件 529 /// </summary> 530 /// <param name="strRemoteFileName">要下載的文件名</param> 531 /// <param name="strFolder">本地目錄(不得以\結束)</param> 532 /// <param name="strLocalFileName">保存在本地時的文件名</param> 533 public void GetNoBinary(string strRemoteFileName, string strFolder, string strLocalFileName) 534 { 535 if (!bConnected) 536 { 537 Connect(); 538 } 539 540 if (strLocalFileName.Equals("")) 541 { 542 strLocalFileName = strRemoteFileName; 543 } 544 Socket socketData = CreateDataSocket(); 545 SendCommand("RETR " + strRemoteFileName); 546 if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226 || iReplyCode == 250)) 547 { 548 throw new IOException(strReply.Substring(4)); 549 } 550 FileStream output = new FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create); 551 while (true) 552 { 553 int iBytes = socketData.Receive(buffer, buffer.Length, 0); 554 output.Write(buffer, 0, iBytes); 555 if (iBytes <= 0) 556 { 557 break; 558 } 559 } 560 output.Close(); 561 if (socketData.Connected) 562 { 563 socketData.Close(); 564 } 565 if (!(iReplyCode == 226 || iReplyCode == 250)) 566 { 567 ReadReply(); 568 if (!(iReplyCode == 226 || iReplyCode == 250)) 569 { 570 throw new IOException(strReply.Substring(4)); 571 } 572 } 573 } 574 575 /// <summary> 576 /// 上傳一批文件 577 /// </summary> 578 /// <param name="strFolder">本地目錄(不得以\結束)</param> 579 /// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param> 580 public void Put(string strFolder, string strFileNameMask) 581 { 582 string[] strFiles = Directory.GetFiles(strFolder, strFileNameMask); 583 foreach (string strFile in strFiles) 584 { 585 Put(strFile); 586 } 587 } 588 589 /// <summary> 590 /// 上傳一個文件 591 /// </summary> 592 /// <param name="strFileName">本地文件名</param> 593 public void Put(string strFileName) 594 { 595 if (!bConnected) 596 { 597 Connect(); 598 } 599 Socket socketData = CreateDataSocket(); 600 if (Path.GetExtension(strFileName) == "") 601 SendCommand("STOR " + Path.GetFileNameWithoutExtension(strFileName)); 602 else 603 SendCommand("STOR " + Path.GetFileName(strFileName)); 604 605 if (!(iReplyCode == 125 || iReplyCode == 150)) 606 { 607 throw new IOException(strReply.Substring(4)); 608 } 609 610 FileStream input = new FileStream(strFileName, FileMode.Open); 611 int iBytes = 0; 612 while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0) 613 { 614 socketData.Send(buffer, iBytes, 0); 615 } 616 input.Close(); 617 if (socketData.Connected) 618 { 619 socketData.Close(); 620 } 621 if (!(iReplyCode == 226 || iReplyCode == 250)) 622 { 623 ReadReply(); 624 if (!(iReplyCode == 226 || iReplyCode == 250)) 625 { 626 throw new IOException(strReply.Substring(4)); 627 } 628 } 629 } 630 631 632 /// <summary> 633 /// 上傳一個文件 634 /// </summary> 635 /// <param name="strFileName">本地文件名</param> 636 public void PutByGuid(string strFileName, string strGuid) 637 { 638 if (!bConnected) 639 { 640 Connect(); 641 } 642 string str = strFileName.Substring(0, strFileName.LastIndexOf("\\")); 643 string strTypeName = strFileName.Substring(strFileName.LastIndexOf(".")); 644 strGuid = str + "\\" + strGuid; 645 System.IO.File.Copy(strFileName, strGuid); 646 System.IO.File.SetAttributes(strGuid, System.IO.FileAttributes.Normal); 647 Socket socketData = CreateDataSocket(); 648 SendCommand("STOR " + Path.GetFileName(strGuid)); 649 if (!(iReplyCode == 125 || iReplyCode == 150)) 650 { 651 throw new IOException(strReply.Substring(4)); 652 } 653 FileStream input = new FileStream(strGuid, FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); 654 int iBytes = 0; 655 while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0) 656 { 657 socketData.Send(buffer, iBytes, 0); 658 } 659 input.Close(); 660 File.Delete(strGuid); 661 if (socketData.Connected) 662 { 663 socketData.Close(); 664 } 665 if (!(iReplyCode == 226 || iReplyCode == 250)) 666 { 667 ReadReply(); 668 if (!(iReplyCode == 226 || iReplyCode == 250)) 669 { 670 throw new IOException(strReply.Substring(4)); 671 } 672 } 673 } 674 #endregion 675 676 #region 目錄操作 677 /// <summary> 678 /// 創建目錄 679 /// </summary> 680 /// <param name="strDirName">目錄名</param> 681 public void MkDir(string strDirName) 682 { 683 if (!bConnected) 684 { 685 Connect(); 686 } 687 SendCommand("MKD " + strDirName); 688 if (iReplyCode != 257) 689 { 690 throw new IOException(strReply.Substring(4)); 691 } 692 } 693 694 /// <summary> 695 /// 刪除目錄 696 /// </summary> 697 /// <param name="strDirName">目錄名</param> 698 public void RmDir(string strDirName) 699 { 700 if (!bConnected) 701 { 702 Connect(); 703 } 704 SendCommand("RMD " + strDirName); 705 if (iReplyCode != 250) 706 { 707 throw new IOException(strReply.Substring(4)); 708 } 709 } 710 711 /// <summary> 712 /// 改變目錄 713 /// </summary> 714 /// <param name="strDirName">新的工作目錄名</param> 715 public void ChDir(string strDirName) 716 { 717 if (strDirName.Equals(".") || strDirName.Equals("")) 718 { 719 return; 720 } 721 if (!bConnected) 722 { 723 Connect(); 724 } 725 SendCommand("CWD " + strDirName); 726 if (iReplyCode != 250) 727 { 728 throw new IOException(strReply.Substring(4)); 729 } 730 this.strRemotePath = strDirName; 731 } 732 #endregion 733 734 #region 內部函數 735 /// <summary> 736 /// 將一行應答字符串記錄在strReply和strMsg,應答碼記錄在iReplyCode 737 /// </summary> 738 private void ReadReply() 739 { 740 strMsg = ""; 741 strReply = ReadLine(); 742 iReplyCode = Int32.Parse(strReply.Substring(0, 3)); 743 } 744 745 /// <summary> 746 /// 建立進行數據連接的socket 747 /// </summary> 748 /// <returns>數據連接socket</returns> 749 private Socket CreateDataSocket() 750 { 751 SendCommand("PASV"); 752 if (iReplyCode != 227) 753 { 754 throw new IOException(strReply.Substring(4)); 755 } 756 int index1 = strReply.IndexOf('('); 757 int index2 = strReply.IndexOf(')'); 758 string ipData = strReply.Substring(index1 + 1, index2 - index1 - 1); 759 int[] parts = new int[6]; 760 int len = ipData.Length; 761 int partCount = 0; 762 string buf = ""; 763 for (int i = 0; i < len && partCount <= 6; i++) 764 { 765 char ch = Char.Parse(ipData.Substring(i, 1)); 766 if (Char.IsDigit(ch)) 767 buf += ch; 768 else if (ch != ',') 769 { 770 throw new IOException("Malformed PASV strReply: " + strReply); 771 } 772 if (ch == ',' || i + 1 == len) 773 { 774 try 775 { 776 parts[partCount++] = Int32.Parse(buf); 777 buf = ""; 778 } 779 catch (Exception) 780 { 781 throw new IOException("Malformed PASV strReply: " + strReply); 782 } 783 } 784 } 785 string ipAddress = parts[0] + "." + parts[1] + "." + parts[2] + "." + parts[3]; 786 int port = (parts[4] << 8) + parts[5]; 787 Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 788 IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ipAddress), port); 789 try 790 { 791 s.Connect(ep); 792 } 793 catch (Exception) 794 { 795 throw new IOException("無法連接ftp服務器"); 796 } 797 return s; 798 } 799 800 /// <summary> 801 /// 關閉socket連接(用於登錄以前) 802 /// </summary> 803 private void CloseSocketConnect() 804 { 805 lock (obj) 806 { 807 if (socketControl != null) 808 { 809 socketControl.Close(); 810 socketControl = null; 811 } 812 bConnected = false; 813 } 814 } 815 816 /// <summary> 817 /// 讀取Socket返回的所有字符串 818 /// </summary> 819 /// <returns>包含應答碼的字符串行</returns> 820 private string ReadLine() 821 { 822 lock (obj) 823 { 824 while (true) 825 { 826 int iBytes = socketControl.Receive(buffer, buffer.Length, 0); 827 strMsg += ASCII.GetString(buffer, 0, iBytes); 828 if (iBytes < buffer.Length) 829 { 830 break; 831 } 832 } 833 } 834 char[] seperator = { '\n' }; 835 string[] mess = strMsg.Split(seperator); 836 if (strMsg.Length > 2) 837 { 838 strMsg = mess[mess.Length - 2]; 839 } 840 else 841 { 842 strMsg = mess[0]; 843 } 844 if (!strMsg.Substring(3, 1).Equals(" ")) //返回字符串正確的是以應答碼(如220開頭,后面接一空格,再接問候字符串) 845 { 846 return ReadLine(); 847 } 848 return strMsg; 849 } 850 851 /// <summary> 852 /// 發送命令並獲取應答碼和最后一行應答字符串 853 /// </summary> 854 /// <param name="strCommand">命令</param> 855 public void SendCommand(String strCommand) 856 { 857 lock (obj) 858 { 859 Byte[] cmdBytes = Encoding.ASCII.GetBytes((strCommand + "\r\n").ToCharArray()); 860 socketControl.Send(cmdBytes, cmdBytes.Length, 0); 861 Thread.Sleep(500); 862 ReadReply(); 863 } 864 } 865 #endregion 866 } 867 }
http://www.cnblogs.com/sufei/archive/2012/12/09/2810197.html
QQ群:108845298,期待你的加入