FTP自動上傳的.Net類
(*).Net中內置的操作FTP的類有:WebClient、 FtpWebRequest。WebClient用起來簡單,但是只能上傳、下載。 FtpWebRequest 比較強大,WebClient內部就是調用FtpWebRequest實現的,如果要實現遍歷ftp文件、創建ftp文件夾等就要用 FtpWebRequest 。
WebClient wc=new WebClient();
wc.Credentials=new NetWorkCredential("用戶名","密碼");
wc.DownLoadFile("網址","文件名");
wc.UpLoadFile("網址","文件名");
WebClient存在一定的缺陷,不能創建目錄等一些更高級一點的操作;
利用FtpWebRequest實現自動上傳的一個類:
using System; using System.Collections.Generic; using System.Net; using System.IO;namespace Lvl.Tools { /// <summary> /// FTP客戶端操作類 /// </summary> public class FtpClient {
#region 構造函數 /// <summary> /// 創建FTP工具 /// <para> /// 默認不使用SSL,使用二進制傳輸方式,使用被動模式 /// </para> /// </summary> /// <param name="host">主機名稱</param> /// <param name="userId">用戶名</param> /// <param name="password">密碼</param> public FtpClient(string host, string userId, string password) : this(host, userId, password, 21, null, false, true, true) { } /// <summary> /// 創建FTP工具 /// </summary> /// <param name="host">主機名稱</param> /// <param name="userId">用戶名</param> /// <param name="password">密碼</param> /// <param name="port">端口</param> /// <param name="enableSsl">允許Ssl</param> /// <param name="proxy">代理</param> /// <param name="useBinary">允許二進制</param> /// <param name="usePassive">允許被動模式</param> public FtpClient(string host, string userId, string password, int port, IWebProxy proxy, bool enableSsl, bool useBinary, bool usePassive) { this.userId = userId; this.password = password; if (host.ToLower().StartsWith("ftp://")) { this.host = host; } else { this.host = "ftp://" + host; } this.port = port; this.proxy = proxy; this.enableSsl = enableSsl; this.useBinary = useBinary; this.usePassive = usePassive; } #endregion #region 主機 private string host = string.Empty; /// <summary> /// 主機 /// </summary> public string Host { get { return this.host ?? string.Empty; } } #endregion #region 登錄用戶名 private string userId = string.Empty; /// <summary> /// 登錄用戶名 /// </summary> public string UserId { get { return this.userId; } } #endregion #region 密碼 private string password = string.Empty; /// <summary> /// 密碼 /// </summary> public string Password { get { return this.password; } } #endregion #region 代理 IWebProxy proxy = null; /// <summary> /// 代理 /// </summary> public IWebProxy Proxy { get { return this.proxy; } set { this.proxy = value; } } #endregion #region 端口 private int port = 21; /// <summary> /// 端口 /// </summary> public int Port { get { return port; } set { this.port = value; } } #endregion #region 設置是否允許Ssl private bool enableSsl = false; /// <summary> /// EnableSsl /// </summary> public bool EnableSsl { get { return enableSsl; } } #endregion #region 使用被動模式 private bool usePassive = true; /// <summary> /// 被動模式 /// </summary> public bool UsePassive { get { return usePassive; } set { this.usePassive = value; } } #endregion #region 二進制方式 private bool useBinary = true; /// <summary> /// 二進制方式 /// </summary> public bool UseBinary { get { return useBinary; } set { this.useBinary = value; } } #endregion #region 遠端路徑 private string remotePath = "/"; /// <summary> /// 遠端路徑 /// <para> /// 返回FTP服務器上的當前路徑(可以是 / 或 /a/../ 的形式) /// </para> /// </summary> public string RemotePath { get { return remotePath; } set { string result = "/"; if (!string.IsNullOrEmpty(value) && value != "/") { result = "/" + value.TrimStart('/').TrimEnd('/') + "/"; } this.remotePath = result; } } #endregion #region 創建一個FTP連接 /// <summary> /// 創建一個FTP請求 /// </summary> /// <param name="url">請求地址</param> /// <param name="method">請求方法</param> /// <returns>FTP請求</returns> private FtpWebRequest CreateRequest(string url, string method) { //建立連接 FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url); request.Credentials = new NetworkCredential(this.userId, this.password); request.Proxy = this.proxy; request.KeepAlive = false;//命令執行完畢之后關閉連接 request.UseBinary = useBinary; request.UsePassive = usePassive; request.EnableSsl = enableSsl; request.Method = method; return request; } #endregion #region 上傳一個文件到遠端路徑下 /// <summary> /// 把文件上傳到FTP服務器的RemotePath下 /// </summary> /// <param name="localFile">本地文件信息</param> /// <param name="remoteFileName">要保存到FTP文件服務器上的名稱</param> public bool Upload(FileInfo localFile, string remoteFileName) { bool result = false; if (localFile.Exists) { string url = Host.TrimEnd('/') + RemotePath + remoteFileName; FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.UploadFile); //上傳數據 using (Stream rs = request.GetRequestStream()) using (FileStream fs = localFile.OpenRead()) { byte[] buffer = new byte[4096];//4K int count = fs.Read(buffer, 0, buffer.Length); while (count > 0) { rs.Write(buffer, 0, count); count = fs.Read(buffer, 0, buffer.Length); } fs.Close(); result = true; } return result; } throw new Exception(string.Format("本地文件不存在,文件路徑:{0}", localFile.FullName)); } #endregion #region 從FTP服務器上下載文件 /// <summary> /// 從當前目錄下下載文件 /// <para> /// 如果本地文件存在,則從本地文件結束的位置開始下載. /// </para> /// </summary> /// <param name="serverName">服務器上的文件名稱</param> /// <param name="localName">本地文件名稱</param> /// <returns>返回一個值,指示是否下載成功</returns> public bool Download(string serverName, string localName) { bool result = false; using (FileStream fs = new FileStream(localName, FileMode.OpenOrCreate)) //創建或打開本地文件 { //建立連接 string url = Host.TrimEnd('/') + RemotePath + serverName; FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.DownloadFile); request.ContentOffset = fs.Length; using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { fs.Position = fs.Length; byte[] buffer = new byte[4096];//4K int count = response.GetResponseStream().Read(buffer, 0, buffer.Length); while (count > 0) { fs.Write(buffer, 0, count); count = response.GetResponseStream().Read(buffer, 0, buffer.Length); } response.GetResponseStream().Close(); } result = true; } return result; } #endregion #region 重命名FTP服務器上的文件 /// <summary> /// 文件更名 /// </summary> /// <param name="oldFileName">原文件名</param> /// <param name="newFileName">新文件名</param> /// <returns>返回一個值,指示更名是否成功</returns> public bool Rename(string oldFileName, string newFileName) { bool result = false; //建立連接 string url = Host.TrimEnd('/') + RemotePath + oldFileName; FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.Rename); request.RenameTo = newFileName; using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { result = true; } return result; } #endregion #region 從當前目錄下獲取文件列表 /// <summary> /// 獲取當前目錄下文件列表 /// </summary> /// <returns></returns> public List<string> GetFileList() { List<string> result = new List<string>(); //建立連接 string url = Host.TrimEnd('/') + RemotePath; FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.ListDirectory); using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default);//中文文件名 string line = reader.ReadLine(); while (line != null) { result.Add(line); line = reader.ReadLine(); } } return result; } #endregion #region 從FTP服務器上獲取文件和文件夾列表 /// <summary> /// 獲取詳細列表 /// </summary> /// <returns></returns> public List<string> GetFileDetails() { List<string> result = new List<string>(); //建立連接 string url = Host.TrimEnd('/') + RemotePath; FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.ListDirectoryDetails); using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default);//中文文件名 string line = reader.ReadLine(); while (line != null) { result.Add(line); line = reader.ReadLine(); } } return result; } #endregion #region 從FTP服務器上刪除文件 /// <summary> /// 刪除FTP服務器上的文件 /// </summary> /// <param name="fileName">文件名稱</param> /// <returns>返回一個值,指示是否刪除成功</returns> public bool DeleteFile(string fileName) { bool result = false; //建立連接 string url = Host.TrimEnd('/') + RemotePath + fileName; FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.DeleteFile); using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { result = true; } return result; } #endregion #region 在FTP服務器上創建目錄 /// <summary> /// 在當前目錄下創建文件夾 /// </summary> /// <param name="dirName">文件夾名稱</param> /// <returns>返回一個值,指示是否創建成功</returns> public bool MakeDirectory(string dirName) { bool result = false; //建立連接 string url = Host.TrimEnd('/') + RemotePath + dirName; FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.MakeDirectory); using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { result = true; } return result; } #endregion #region 從FTP服務器上刪除目錄 /// <summary> /// 刪除文件夾 /// </summary> /// <param name="dirName">文件夾名稱</param> /// <returns>返回一個值,指示是否刪除成功</returns> public bool DeleteDirectory(string dirName) { bool result = false; //建立連接 string url = Host.TrimEnd('/') + RemotePath + dirName; FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.RemoveDirectory); using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { result = true; } return result; } #endregion #region 從FTP服務器上獲取文件大小 /// <summary> /// 獲取文件大小 /// </summary> /// <param name="fileName"></param> /// <returns></returns> public long GetFileSize(string fileName) { long result = 0; //建立連接 string url = Host.TrimEnd('/') + RemotePath + fileName; FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.GetFileSize); using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { result = response.ContentLength; } return result; } #endregion #region 給FTP服務器上的文件追加內容 /// <summary> /// 給FTP服務器上的文件追加內容 /// </summary> /// <param name="localFile">本地文件</param> /// <param name="remoteFileName">FTP服務器上的文件</param> /// <returns>返回一個值,指示是否追加成功</returns> public bool Append(FileInfo localFile, string remoteFileName) { if (localFile.Exists) { using (FileStream fs = new FileStream(localFile.FullName, FileMode.Open)) { return Append(fs, remoteFileName); } } throw new Exception(string.Format("本地文件不存在,文件路徑:{0}", localFile.FullName)); } /// <summary> /// 給FTP服務器上的文件追加內容 /// </summary> /// <param name="stream">數據流(可通過設置偏移來實現從特定位置開始上傳)</param> /// <param name="remoteFileName">FTP服務器上的文件</param> /// <returns>返回一個值,指示是否追加成功</returns> public bool Append(Stream stream, string remoteFileName) { bool result = false; if (stream != null && stream.CanRead) { //建立連接 string url = Host.TrimEnd('/') + RemotePath + remoteFileName; FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.AppendFile); using (Stream rs = request.GetRequestStream()) { //上傳數據 byte[] buffer = new byte[4096];//4K int count = stream.Read(buffer, 0, buffer.Length); while (count > 0) { rs.Write(buffer, 0, count); count = stream.Read(buffer, 0, buffer.Length); } result = true; } } return result; } #endregion #region 獲取FTP服務器上的當前路徑 /// <summary> /// 獲取FTP服務器上的當前路徑 /// </summary> public string CurrentDirectory { get { string result = string.Empty; string url = Host.TrimEnd('/') + RemotePath; FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.PrintWorkingDirectory); using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { string temp = response.StatusDescription; int start = temp.IndexOf('"') + 1; int end = temp.LastIndexOf('"'); if (end >= start) { result = temp.Substring(start, end - start); } } return result; } } #endregion #region 檢查當前路徑上是否存在某個文件 /// <summary> /// 檢查文件是否存在 /// </summary> /// <param name="fileName">要檢查的文件名</param> /// <returns>返回一個值,指示要檢查的文件是否存在</returns> public bool CheckFileExist(string fileName) { bool result = false; if (fileName != null && fileName.Trim().Length > 0) { fileName = fileName.Trim(); List<string> files = GetFileList(); if (files != null && files.Count > 0) { foreach (string file in files) { if (file.ToLower() == fileName.ToLower()) { result = true; break; } } } } return result; } #endregion }
}
/* FTP全狀態碼查詢詞典
1xx - 肯定的初步答復 這些狀態代碼指示一項操作已經成功開始,但客戶端希望在繼續操作新命令前得到另一個答復。 ? 110 重新啟動標記答復。 ? 120 服務已就緒,在 nnn 分鐘后開始。 ? 125 數據連接已打開,正在開始傳輸。 ? 150 文件狀態正常,準備打開數據連接。
2xx - 肯定的完成答復 一項操作已經成功完成。客戶端可以執行新命令。 ? 200 命令確定。 ? 202 未執行命令,站點上的命令過多。 ? 211 系統狀態,或系統幫助答復。 ? 212 目錄狀態。 ? 213 文件狀態。 ? 214 幫助消息。 ? 215 NAME 系統類型,其中,NAME 是 Assigned Numbers 文檔中所列的正式系統名稱。 ? 220 服務就緒,可以執行新用戶的請求。 ? 221 服務關閉控制連接。如果適當,請注銷。 ? 225 數據連接打開,沒有進行中的傳輸。 ? 226 關閉數據連接。請求的文件操作已成功(例如,傳輸文件或放棄文件)。 ? 227 進入被動模式 (h1,h2,h3,h4,p1,p2)。 ? 230 用戶已登錄,繼續進行。 ? 250 請求的文件操作正確,已完成。 ? 257 已創建“PATHNAME”。
3xx - 肯定的中間答復 該命令已成功,但服務器需要更多來自客戶端的信息以完成對請求的處理。 ? 331 用戶名正確,需要密碼。 ? 332 需要登錄帳戶。 ? 350 請求的文件操作正在等待進一步的信息。
4xx - 瞬態否定的完成答復 該命令不成功,但錯誤是暫時的。如果客戶端重試命令,可能會執行成功。 ? 421 服務不可用,正在關閉控制連接。如果服務確定它必須關閉,將向任何命令發送這一應答。 ? 425 無法打開數據連接。 ? 426 Connection closed; transfer aborted. ? 450 未執行請求的文件操作。文件不可用(例如,文件繁忙)。 ? 451 請求的操作異常終止:正在處理本地錯誤。 ? 452 未執行請求的操作。系統存儲空間不夠。
5xx - 永久性否定的完成答復 該命令不成功,錯誤是永久性的。如果客戶端重試命令,將再次出現同樣的錯誤。 ? 500 語法錯誤,命令無法識別。這可能包括諸如命令行太長之類的錯誤。 ? 501 在參數中有語法錯誤。 ? 502 未執行命令。 ? 503 錯誤的命令序列。 ? 504 未執行該參數的命令。 ? 530 未登錄。 ? 532 存儲文件需要帳戶。 ? 550 未執行請求的操作。文件不可用(例如,未找到文件,沒有訪問權限)。 ? 551 請求的操作異常終止:未知的頁面類型。 ? 552 請求的文件操作異常終止:超出存儲分配(對于當前目錄或數據集)。 ? 553 未執行請求的操作。不允許的文件名。 常見的 FTP 狀態代碼及其原因 ? 150 - FTP 使用兩個端口:21 用于發送命令,20 用于發送數據。狀態代碼 150 表示服務器準備在端口 20 上打開新連接,發送一些數據。 ? 226 - 命令在端口 20 上打開數據連接以執行操作,如傳輸文件。該操作成功完成,數據連接已關閉。 ? 230 - 客戶端發送正確的密碼后,顯示該狀態代碼。它表示用戶已成功登錄。 ? 331 - 客戶端發送用戶名后,顯示該狀態代碼。無論所提供的用戶名是否為系統中的有效帳戶,都將顯示該狀態代碼。 ? 426 - 命令打開數據連接以執行操作,但該操作已被取消,數據連接已關閉。 ? 530 - 該狀態代碼表示用戶無法登錄,因為用戶名和密碼組合無效。如果使用某個用戶帳戶登錄,可能鍵入錯誤的用戶名或密碼,也可能選擇只允許匿名訪問。如果使用匿名帳戶登錄,IIS 的配置可能拒絕匿名訪問。 ? 550 - 命令未被執行,因為指定的文件不可用。例如,要 GET 的文件并不存在,或試圖將文件 PUT 到您沒有寫入權限的目錄。 */</pre>