該類轉自:http://blog.csdn.net/byshome/article/details/5801991,稍作修改
using System; using System.Net; using System.Net.Sockets; using System.Collections.Generic; using System.Text; using System.IO; using System.Globalization; using System.Text.RegularExpressions; namespace FTP { public class FTPHelper : IDisposable { #region 聲明事件 /// <summary> /// 正在下載文件 /// </summary> public event FTPSendEventHandler FileDownloading; private delegate void OnFileDownloadingDelegate(FTPConnect ftpConnect, long lTotalBytes, long lBytesTransfered); /// <summary> /// 正在下載文件封裝模式 /// </summary> private void OnFileDownloading(FTPConnect ftpConnect, long lTotalBytes, long lBytesTransfered) { if (this.FileDownloading != null) { if (lBytesTransfered > lTotalBytes) lBytesTransfered = lTotalBytes; System.ComponentModel.ISynchronizeInvoke aSynch = this.FileDownloading.Target as System.ComponentModel.ISynchronizeInvoke; if (aSynch != null && aSynch.InvokeRequired) aSynch.Invoke(new OnFileDownloadingDelegate(OnFileDownloading), new object[] { ftpConnect, lTotalBytes, lBytesTransfered }); else this.FileDownloading(ftpConnect, new FTPSendEventArgs(lTotalBytes, lBytesTransfered)); } } /// <summary> /// 文件下載完成 /// </summary> public event EventHandler FileDownloadCompleted; private delegate void OnFileDownloadCompletedDelegate(FTPConnect ftpConnect); /// <summary> /// 文件下載完成封裝模式 /// </summary> private void OnFileDownloadCompleted(FTPConnect ftpConnect) { if (this.FileDownloadCompleted != null) { System.ComponentModel.ISynchronizeInvoke aSynch = this.FileDownloadCompleted.Target as System.ComponentModel.ISynchronizeInvoke; if (aSynch != null && aSynch.InvokeRequired) aSynch.Invoke(new OnFileDownloadCompletedDelegate(OnFileDownloadCompleted), new object[] { ftpConnect }); else this.FileDownloadCompleted(ftpConnect, new EventArgs()); } } /// <summary> /// 取消正在下載的文件 /// </summary> public event EventHandler FileDownloadCanceled; private delegate void OnFileDownloadCanceledDelegate(FTPConnect ftpConnect); /// <summary> /// 取消正在下載的文件封裝模式 /// </summary> private void OnFileDownloadCanceled(FTPConnect ftpConnect) { if (this.FileDownloadCanceled != null) { System.ComponentModel.ISynchronizeInvoke aSynch = this.FileDownloadCanceled.Target as System.ComponentModel.ISynchronizeInvoke; if (aSynch != null && aSynch.InvokeRequired) aSynch.Invoke(new OnFileDownloadCanceledDelegate(OnFileDownloadCanceled), new object[] { ftpConnect }); else this.FileDownloadCanceled(ftpConnect, new EventArgs()); } } /// <summary> /// 正在上傳文件 /// </summary> public event FTPSendEventHandler FileUploading; private delegate void OnFileUploadingDelegate(FTPConnect ftpConnect, long lTotalBytes, long lBytesTransfered); /// <summary> /// 正在下載事件封裝模式 /// </summary> /// <param name="lTotalBytes"></param> /// <param name="lBytesTransfered"></param> private void OnFileUploading(FTPConnect ftpConnect, long lTotalBytes, long lBytesTransfered) { if (this.FileUploading != null) { if (lBytesTransfered > lTotalBytes) lBytesTransfered = lTotalBytes; System.ComponentModel.ISynchronizeInvoke aSynch = this.FileUploading.Target as System.ComponentModel.ISynchronizeInvoke; if (aSynch != null && aSynch.InvokeRequired) aSynch.Invoke(new OnFileUploadingDelegate(OnFileUploading), new object[] { ftpConnect, lTotalBytes, lBytesTransfered }); else this.FileUploading(ftpConnect, new FTPSendEventArgs(lTotalBytes, lBytesTransfered)); } } /// <summary> /// 文件上傳完成 /// </summary> public event EventHandler FileUploadCompleted; private delegate void OnFileUploadCompletedDelegate(FTPConnect ftpConnect); private void OnFileUploadCompleted(FTPConnect ftpConnect) { if (this.FileUploadCompleted != null) { System.ComponentModel.ISynchronizeInvoke aSynch = this.FileUploadCompleted.Target as System.ComponentModel.ISynchronizeInvoke; if (aSynch != null && aSynch.InvokeRequired) aSynch.Invoke(new OnFileUploadCompletedDelegate(OnFileUploadCompleted), new object[] { ftpConnect }); else this.FileUploadCompleted(ftpConnect, new EventArgs()); } } /// <summary> /// 取消了上傳文件 /// </summary> public event EventHandler FileUploadCanceled; private delegate void OnFileUploadCanceledDelegate(FTPConnect ftpConnect); private void OnFileUploadCanceled(FTPConnect ftpConnect) { if (this.FileUploadCanceled != null) { System.ComponentModel.ISynchronizeInvoke aSynch = this.FileUploadCanceled.Target as System.ComponentModel.ISynchronizeInvoke; if (aSynch != null && aSynch.InvokeRequired) aSynch.Invoke(new OnFileUploadCanceledDelegate(OnFileUploadCanceled), new object[] { ftpConnect }); else this.FileUploadCanceled(ftpConnect, new EventArgs()); } } /// <summary> /// 傳輸過程發生錯誤事件 /// </summary> public event FTPErrorEventHandler FtpError; private delegate void OnFtpErrorDelegate(FTPConnect ftpConnect, Exception error); public void OnFtpError(FTPConnect ftpConnect, Exception error) { if (this.FtpError != null) { System.ComponentModel.ISynchronizeInvoke aSynch = this.FtpError.Target as System.ComponentModel.ISynchronizeInvoke; if (aSynch != null && aSynch.InvokeRequired) aSynch.Invoke(new OnFtpErrorDelegate(OnFtpError), new object[] { ftpConnect, error }); else this.FtpError(ftpConnect, new FTPErrorEventArgs(error)); } } #endregion #region FTPUrl結構 public class FTPUrl { private string m_Url = String.Empty; private string m_RemoteHost = String.Empty; private IPAddress m_RemoteHostIP = IPAddress.None; private int m_RemotePort = 21; private string m_UserName = String.Empty; private string m_Password = String.Empty; private string m_SubUrl = String.Empty; public FTPUrl() { } public FTPUrl(string url) { this.Url = url; } /// <summary> /// FTP的全地址 /// </summary> public string Url { get { return this.m_Url; } set { if (value.IndexOf("@") < 0) throw (new Exception("FTP地址路徑不合法!格式應為ftp://用戶名:密碼@地址[:端口]/")); string strSubUrl = ""; string strRemoteHostAndPort = value.Substring(value.IndexOf("@") + 1); if (strRemoteHostAndPort.IndexOf("/") > 0) { strSubUrl = strRemoteHostAndPort.Substring(strRemoteHostAndPort.IndexOf("/")); strRemoteHostAndPort = strRemoteHostAndPort.Substring(0, strRemoteHostAndPort.IndexOf("/")); } string strRemoteHost = strRemoteHostAndPort; int iRemotePort = 21; if (strRemoteHostAndPort.IndexOf(":") > 0) { strRemoteHost = strRemoteHostAndPort.Substring(0, strRemoteHostAndPort.IndexOf(":")); string strRemotePort = strRemoteHostAndPort.Substring(strRemoteHostAndPort.IndexOf(":") + 1); if (!int.TryParse(strRemotePort, out iRemotePort)) iRemotePort = 21; } string strUserNameAndPassword = value.Substring(0, value.IndexOf("@")).Trim(); if (strUserNameAndPassword.ToLower().StartsWith("ftp://")) strUserNameAndPassword = strUserNameAndPassword.Substring(6).Trim(); if (strUserNameAndPassword == string.Empty || strUserNameAndPassword.IndexOf(":") < 0) throw (new Exception("FTP地址路徑不合法!格式應為ftp://用戶名:密碼@地址[:端口]/")); string strUserName = strUserNameAndPassword.Substring(0, strUserNameAndPassword.IndexOf(":")); string strPassword = strUserNameAndPassword.Substring(strUserNameAndPassword.IndexOf(":") + 1); IPAddress[] ips = Dns.GetHostAddresses(strRemoteHost); if (ips.Length == 0) throw (new Exception("FTP地址路徑中主機地址無效!")); strSubUrl = strSubUrl.Replace("//", "/"); this.m_RemoteHostIP = ips[0]; this.m_RemoteHost = strRemoteHost; this.m_RemotePort = iRemotePort; this.m_UserName = strUserName; this.m_Password = strPassword; this.m_SubUrl = strSubUrl; this.m_Url = value; } } /// <summary> /// 主機地址 /// </summary> public string RemoteHost { get { return this.m_RemoteHost; } } /// <summary> /// 主機IP /// </summary> public IPAddress RemoteHostIP { get { return this.m_RemoteHostIP; } } /// <summary> /// 主機端口 /// </summary> public int RemotePort { get { return this.m_RemotePort; } } public string UserName { get { return this.m_UserName; } } public string Password { get { return this.m_Password; } } public string SubUrl { get { return this.m_SubUrl; } } } #endregion #region 傳輸模式 /// <summary> /// 傳輸模式:二進制類型、ASCII類型 /// </summary> public enum TransferType { /// <summary> /// Binary /// </summary> Binary, /// <summary> /// ASCII /// </summary> ASCII }; #endregion #region 存貯FTP的連接結構類 public class FTPConnect { #region 私有字段 /// <summary> /// 數據傳送套接字列表 /// </summary> private List<Socket> m_DataSocketList; private string m_ID; /// <summary> /// 唯一ID /// </summary> public string ID { get { return this.m_ID; } } private object m_Tag = null; /// <summary> /// 擴展標記 /// </summary> public object Tag { get { return this.m_Tag; } set { this.m_Tag = value; } } private bool m_DataTransmitting = false; /// <summary> /// 數據正在傳輸 標記 /// </summary> public bool DataTransmitting { get { return this.m_DataTransmitting; } set { this.m_DataTransmitting = value; } } private Socket m_SocketControl; /// <summary> /// FTPUrl /// </summary> private FTPUrl m_FTPUrl; /// <summary> /// 是否已經連接 /// </summary> private bool m_IsConnected; private Encoding m_EncodeType = Encoding.Default; /// <summary> /// 編碼方式 /// </summary> public Encoding EncodeType { get { return this.m_EncodeType; } set { this.m_EncodeType = value; } } /// <summary> /// 接收和發送數據的緩沖區 /// </summary> private static int BLOCK_SIZE = 512; /// <summary> /// 緩沖區大小 /// </summary> private Byte[] m_Buffer; public Byte[] Buffer { get { return this.m_Buffer; } set { this.m_Buffer = value; } } private string m_Message; /// <summary> /// 當前的消息 /// </summary> public string Message { get { return this.m_Message; } set { this.m_Message = value; } } private string m_ReplyString; /// <summary> /// 應答字符串 /// </summary> public string ReplyString { get { return this.m_ReplyString; } set { this.m_ReplyString = value; } } private int m_ReplyCode; /// <summary> /// 應答代碼 /// </summary> public int ReplyCode { get { return this.m_ReplyCode; } set { this.m_ReplyCode = value; } } /// <summary> /// 傳輸模式 /// </summary> private TransferType trType; #endregion public FTPConnect() { this.m_ID = System.Guid.NewGuid().ToString(); this.m_DataSocketList = new List<Socket>(); this.m_Buffer = new Byte[BLOCK_SIZE]; } public FTPConnect(FTPUrl ftpUrl) { this.m_ID = System.Guid.NewGuid().ToString(); this.m_DataSocketList = new List<Socket>(); this.m_Buffer = new Byte[BLOCK_SIZE]; this.FTPUrl = ftpUrl; } public FTPConnect(FTPUrl ftpUrl, string ftpId) { if (String.IsNullOrEmpty(ftpId)) ftpId = System.Guid.NewGuid().ToString(); this.m_ID = ftpId; this.m_DataSocketList = new List<Socket>(); this.m_Buffer = new Byte[BLOCK_SIZE]; this.FTPUrl = ftpUrl; } #region 公共字段 /// <summary> /// 套接字連接 /// </summary> public Socket SocketControl { get { return this.m_SocketControl; } set { this.m_SocketControl = value; } } /// <summary> /// 對應的URL /// </summary> public FTPUrl FTPUrl { get { return this.m_FTPUrl; } set { this.m_FTPUrl = value; } } /// <summary> /// 是否已經連接 /// </summary> public bool IsConnected { get { return this.m_IsConnected; } set { this.m_IsConnected = value; } } #endregion #region 公共方法 #region 取消傳送數據 public void CancelDataTransmit() { this.m_DataTransmitting = false; } #endregion #region 發送命令 /// <summary> /// 發送命令並獲取應答碼和最后一行應答字符串 /// </summary> /// <param name="strCommand">命令</param> public void SendCommand(string strCommand) { if (this.m_SocketControl == null) throw (new Exception("請先連接服務器再進行操作!")); Byte[] cmdBytes = m_EncodeType.GetBytes((strCommand + "\r\n").ToCharArray()); this.m_SocketControl.Send(cmdBytes, cmdBytes.Length, 0); this.ReadReply(); } #endregion #region 讀取最后一行的消息 /// <summary> /// 讀取Socket返回的所有字符串 /// </summary> /// <returns>包含應答碼的字符串行</returns> private string ReadLine() { if (this.m_SocketControl == null) throw (new Exception("請先連接服務器再進行操作!")); while (true) { int iBytes = this.m_SocketControl.Receive(m_Buffer, m_Buffer.Length, 0); m_Message += m_EncodeType.GetString(m_Buffer, 0, iBytes); if (iBytes < m_Buffer.Length) { break; } } char[] seperator = { '\n' }; string[] mess = m_Message.Split(seperator); if (m_Message.Length > 2) { m_Message = mess[mess.Length - 2]; //seperator[0]是10,換行符是由13和0組成的,分隔后10后面雖沒有字符串, //但也會分配為空字符串給后面(也是最后一個)字符串數組, //所以最后一個mess是沒用的空字符串 //但為什么不直接取mess[0],因為只有最后一行字符串應答碼與信息之間有空格 } else { m_Message = mess[0]; } if (!m_Message.Substring(3, 1).Equals(" "))//返回字符串正確的是以應答碼(如220開頭,后面接一空格,再接問候字符串) { return this.ReadLine(); } return m_Message; } #endregion #region 讀取應答代碼 /// <summary> /// 將一行應答字符串記錄在strReply和strMsg /// 應答碼記錄在iReplyCode /// </summary> public void ReadReply() { this.m_Message = ""; this.m_ReplyString = this.ReadLine(); this.m_ReplyCode = Int32.Parse(m_ReplyString.Substring(0, 3)); } #endregion #region 斷開連接 /// <summary> /// 關閉連接 /// </summary> public void DisConnect() { this.m_DataTransmitting = false; while (this.m_DataSocketList.Count > 0) { Socket socket = this.m_DataSocketList[0]; if (socket != null && socket.Connected) socket.Close(); this.m_DataSocketList.RemoveAt(0); } if (this.m_IsConnected && this.m_SocketControl != null) this.SendCommand("QUIT"); this.CloseSocketConnect(); this.m_Buffer = null; } /// <summary> /// 關閉socket連接(用於登錄以前) /// </summary> private void CloseSocketConnect() { if (this.m_SocketControl != null && this.m_SocketControl.Connected) { this.m_SocketControl.Close(); this.m_SocketControl = null; } this.m_IsConnected = false; } #endregion #region 連接服務器 public void Connect() { this.DisConnect();//先斷開現有連接 this.m_Buffer = new byte[BLOCK_SIZE]; this.m_SocketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ep = new IPEndPoint(this.m_FTPUrl.RemoteHostIP, this.m_FTPUrl.RemotePort); try { this.m_SocketControl.Connect(ep); } catch (Exception) { throw new IOException(String.Format("無法連接到遠程服務器{0}!", this.m_FTPUrl.RemoteHost)); } // 獲取應答碼 this.ReadReply(); if (m_ReplyCode != 220) { this.DisConnect(); throw new IOException(m_ReplyString.Substring(4)); } // 登陸 this.SendCommand("USER " + this.m_FTPUrl.UserName); if (!(m_ReplyCode == 331 || m_ReplyCode == 230)) { this.CloseSocketConnect();//關閉連接 throw new IOException(m_ReplyString.Substring(4)); } if (m_ReplyCode != 230) { this.SendCommand("PASS " + this.m_FTPUrl.Password); if (!(m_ReplyCode == 230 || m_ReplyCode == 202)) { this.CloseSocketConnect();//關閉連接 throw new IOException(m_ReplyString.Substring(4)); } } this.m_IsConnected = true; } #endregion #region 改變目錄 /// <summary> /// 改變目錄 /// </summary> /// <param name="strDirName">新的工作目錄名</param> public void ChangeDir(string dirName) { if (!this.m_IsConnected) throw (new Exception("請先連接服務器然后再進行CWD操作!")); if (dirName.Equals(".") || dirName.Equals("")) return; this.SendCommand("CWD " + dirName); if (m_ReplyCode != 250) throw new IOException(m_ReplyString.Substring(4)); } #endregion #region 傳輸模式 /// <summary> /// 設置傳輸模式 /// </summary> /// <param name="ttType">傳輸模式</param> public void SetTransferType(TransferType ttType) { if (ttType == TransferType.Binary) { this.SendCommand("TYPE I");//binary類型傳輸 } else { this.SendCommand("TYPE A");//ASCII類型傳輸 } if (m_ReplyCode != 200) { throw new IOException(m_ReplyString.Substring(4)); } else { trType = ttType; } } /// <summary> /// 獲得傳輸模式 /// </summary> /// <returns>傳輸模式</returns> public TransferType GetTransferType() { return trType; } #endregion #region 建立進行數據連接的socket /// <summary> /// 建立進行數據連接的socket /// </summary> /// <returns>數據連接socket</returns> public Socket CreateDataSocket() { this.SendCommand("PASV"); if (this.m_ReplyCode != 227) throw new IOException(this.m_ReplyString.Substring(4)); int index1 = this.m_ReplyString.IndexOf('('); int index2 = this.m_ReplyString.IndexOf(')'); string ipData = this.m_ReplyString.Substring(index1 + 1, index2 - index1 - 1); int[] parts = new int[6]; int len = ipData.Length; int partCount = 0; string buf = ""; for (int i = 0; i < len && partCount <= 6; i++) { char ch = Char.Parse(ipData.Substring(i, 1)); if (Char.IsDigit(ch)) buf += ch; else if (ch != ',') { throw new IOException("Malformed PASV Reply: " + this.m_ReplyString); } if (ch == ',' || i + 1 == len) { try { parts[partCount++] = Int32.Parse(buf); buf = ""; } catch (Exception) { throw new IOException("Malformed PASV Reply: " + this.m_ReplyString); } } } string ipAddress = parts[0] + "." + parts[1] + "." + parts[2] + "." + parts[3]; int port = (parts[4] << 8) + parts[5]; Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ipAddress), port); try { socket.Connect(ep); } catch (Exception) { throw new IOException(String.Format("無法連接到遠程服務器{0}:{1}!", ipAddress, port)); } this.m_DataSocketList.Add(socket); return socket; } #endregion #endregion } #endregion #region 變量區 /// <summary> /// 進行控制連接的socket /// </summary> private List<FTPConnect> m_FTPConnectList; private object m_Tag; /// <summary> /// 標記 /// </summary> public object Tag { get { return this.m_Tag; } set { this.m_Tag = value; } } #endregion #region 實例化 public FTPHelper() { this.m_FTPConnectList = new List<FTPConnect>(); } #endregion #region Dispose public void Dispose() { while (this.m_FTPConnectList.Count > 0) { FTPConnect ftpConnect = this.m_FTPConnectList[0]; ftpConnect.DisConnect(); this.m_FTPConnectList.Remove(ftpConnect); } } #endregion #region 得到文件大小 /// <summary> /// 得到文件大小 /// </summary> /// <param name="fileUrl">目標文件,包含用戶名與密碼。如:ftp://username:password@127.0.0.1/1.txt</param> /// <param name="UserName">用戶名</param> /// <param name="Password">密碼</param> /// <returns></returns> public long GetFileSize(string fileUrl) { FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; try { ftpUrl = new FTPUrl(fileUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); string strDirName = ftpUrl.SubUrl; if (strDirName.IndexOf("/") >= 0) strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/")); ftpConnect.ChangeDir(strDirName); ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl)); long lFileSize = 0; if (ftpConnect.ReplyCode == 213) lFileSize = Int64.Parse(ftpConnect.ReplyString.Substring(4)); else throw new IOException(ftpConnect.ReplyString.Substring(4)); return lFileSize; } catch (Exception ex) { throw (ex); } finally { if (ftpConnect != null) ftpConnect.DisConnect(); } } #endregion #region 得到文件大小 /// <summary> /// 得到文件大小 /// </summary> /// <param name="fileUrl">目標文件,包含用戶名與密碼。如:ftp://username:password@127.0.0.1/1.txt</param> /// <param name="UserName">用戶名</param> /// <param name="Password">密碼</param> /// <returns></returns> public DateTime GetDateTimestamp(string fileUrl) { FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; try { ftpUrl = new FTPUrl(fileUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); string strDirName = ftpUrl.SubUrl; if (strDirName.IndexOf("/") >= 0) strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/")); ftpConnect.ChangeDir(strDirName); ftpConnect.SendCommand("MDTM " + Path.GetFileName(ftpUrl.SubUrl)); if (ftpConnect.ReplyCode == 213) { string strDateTime = ftpConnect.ReplyString.Substring(4); int iYear = 0, iMonth = 0, iDay = 0, iHour = 0, iMinute = 0, iSecond = 0; if (strDateTime.Length >= 4) int.TryParse(strDateTime.Substring(0, 4), out iYear); if (strDateTime.Length >= 6) int.TryParse(strDateTime.Substring(4, 2), out iMonth); if (strDateTime.Length >= 8) int.TryParse(strDateTime.Substring(6, 2), out iDay); if (strDateTime.Length >= 10) int.TryParse(strDateTime.Substring(8, 2), out iHour); if (strDateTime.Length >= 12) int.TryParse(strDateTime.Substring(10, 2), out iMinute); if (strDateTime.Length >= 14) int.TryParse(strDateTime.Substring(12, 2), out iSecond); return new DateTime(iYear, iMonth, iDay, iHour, iMinute, iSecond).ToLocalTime(); } else throw new IOException(ftpConnect.ReplyString.Substring(4)); } catch (Exception ex) { throw (ex); } finally { if (ftpConnect != null) ftpConnect.DisConnect(); } } #endregion #region 刪除指定的文件 /// <summary> /// 刪除指定的文件 /// </summary> /// <param name="fileUrl">待刪除文件名</param> public void DeleteFile(string fileUrl) { FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; try { ftpUrl = new FTPUrl(fileUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); string strDirName = ftpUrl.SubUrl; if (strDirName.IndexOf("/") >= 0) strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/")); ftpConnect.ChangeDir(strDirName); ftpConnect.SendCommand("DELE " + Path.GetFileName(ftpUrl.SubUrl)); if (ftpConnect.ReplyCode != 250) throw (new Exception(ftpConnect.ReplyString.Substring(4))); } catch (Exception ex) { throw (ex); } finally { if (ftpConnect != null) ftpConnect.DisConnect(); } } #endregion #region 重命名 /// <summary> /// 重命名(如果新文件名與已有文件重名,將覆蓋已有文件) /// </summary> /// <param name="strOldFileName">舊文件名</param> /// <param name="strNewFileName">新文件名</param> public void Rename(string originalUrl, string newName) { FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; try { ftpUrl = new FTPUrl(originalUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); string strDirName = ftpUrl.SubUrl; if (strDirName.IndexOf("/") >= 0) strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/")); ftpConnect.ChangeDir(strDirName); ftpConnect.SendCommand("RNFR " + Path.GetFileName(ftpUrl.SubUrl)); if (ftpConnect.ReplyCode != 350) throw (new Exception(ftpConnect.ReplyString.Substring(4))); ftpConnect.SendCommand("RNTO " + newName); if (ftpConnect.ReplyCode != 250) throw (new Exception(ftpConnect.ReplyString.Substring(4))); } catch (Exception ex) { throw (ex); } finally { if (ftpConnect != null) ftpConnect.DisConnect(); } } #endregion #region 創建文件夾 public void MakeDirectory(string dirUrl) { FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; int iCharIndex = 0; string strDirUrl, strDirUrlTemp; try { ftpUrl = new FTPUrl(dirUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); strDirUrl = ftpUrl.SubUrl; while (true && strDirUrl.Trim() != "") { iCharIndex = strDirUrl.IndexOf("/", iCharIndex) + 1; if (iCharIndex == 0) strDirUrlTemp = strDirUrl; else strDirUrlTemp = strDirUrl.Substring(0, iCharIndex); if (strDirUrlTemp == "") continue; ftpConnect.SendCommand("MKD " + strDirUrlTemp); if (ftpConnect.ReplyCode != 257 && ftpConnect.ReplyCode != 550) throw new IOException(ftpConnect.ReplyString.Substring(4)); if (strDirUrlTemp == strDirUrl) break; } } catch (Exception ex) { throw (ex); } finally { if (ftpConnect != null) ftpConnect.DisConnect(); } } #endregion #region 刪除目錄 /// <summary> /// 刪除目錄 /// </summary> /// <param name="dirUrl">目錄名</param> public void RemoveDirectory(string dirUrl) { FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; try { ftpUrl = new FTPUrl(dirUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); string strDirPath = ftpUrl.SubUrl; string strDirName = ftpUrl.SubUrl; if (strDirPath.IndexOf("/") >= 0) { strDirPath = strDirPath.Substring(0, strDirPath.LastIndexOf("/")); strDirName = strDirPath.Substring(strDirPath.LastIndexOf("/") + 1); } ftpConnect.ChangeDir(strDirPath); ftpConnect.SendCommand("RMD " + strDirName); if (ftpConnect.ReplyCode != 250) throw (new Exception(ftpConnect.ReplyString.Substring(4))); } catch (Exception ex) { throw (ex); } finally { if (ftpConnect != null) ftpConnect.DisConnect(); } } #endregion #region 得到簡單的文件列表 public string[] ListDirectoryFile(string listUrl) { FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; Socket socketData = null; try { ftpUrl = new FTPUrl(listUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); string strDirPath = ftpUrl.SubUrl; if (strDirPath.IndexOf("/") >= 0) strDirPath = strDirPath.Substring(0, strDirPath.LastIndexOf("/")); ftpConnect.ChangeDir(strDirPath); socketData = ftpConnect.CreateDataSocket(); ftpConnect.SendCommand("NLST"); if (ftpConnect.ReplyCode != 150 && ftpConnect.ReplyCode != 125) throw new IOException(ftpConnect.ReplyString.Substring(4)); //獲得結果 ftpConnect.Message = ""; while (true) { int iBytes = socketData.Receive(ftpConnect.Buffer, ftpConnect.Buffer.Length, 0); ftpConnect.Message += ftpConnect.EncodeType.GetString(ftpConnect.Buffer, 0, iBytes); if (iBytes < ftpConnect.Buffer.Length) break; } ftpConnect.Message = ftpConnect.Message.Replace('\r', ' '); char[] seperator = { '\n' }; string[] strsFileList = ftpConnect.Message.Split(seperator); socketData.Close();//數據socket關閉時也會有返回碼 socketData = null; if (ftpConnect.ReplyCode != 226) { ftpConnect.ReadReply(); if (ftpConnect.ReplyCode != 226) throw new IOException(ftpConnect.ReplyString.Substring(4)); } return strsFileList; } catch (Exception ex) { throw (ex); } finally { if (socketData != null && socketData.Connected) socketData.Close(); socketData = null; if (ftpConnect != null) ftpConnect.DisConnect(); } } //獲取當前目錄下的目錄 public List<string> ListDirectory(string listUrl) { List<string> strsFileList = new List<string>(); List<FileStruct> files = ListDirectoryDetails(listUrl); foreach (FileStruct fs in files) { if (fs.IsDirectory) { strsFileList.Add(fs.Name); } } return strsFileList; } #endregion #region 得到詳細的文件列表 public List<FileStruct> ListDirectoryDetails(string listUrl) { FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; Socket socketData = null; try { ftpUrl = new FTPUrl(listUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); string strDirPath = ftpUrl.SubUrl; if (strDirPath.IndexOf("/") >= 0) strDirPath = strDirPath.Substring(0, strDirPath.LastIndexOf("/")); ftpConnect.ChangeDir(strDirPath); socketData = ftpConnect.CreateDataSocket(); ftpConnect.SendCommand("LIST"); if (ftpConnect.ReplyCode != 150 && ftpConnect.ReplyCode != 125) throw new IOException(ftpConnect.ReplyString.Substring(4)); //獲得結果 ftpConnect.Message = ""; while (true) { int iBytes = socketData.Receive(ftpConnect.Buffer, ftpConnect.Buffer.Length, 0); ftpConnect.Message += ftpConnect.EncodeType.GetString(ftpConnect.Buffer, 0, iBytes); if (iBytes < ftpConnect.Buffer.Length) break; } if (ftpConnect.Message.StartsWith("t")) ftpConnect.Message = ftpConnect.Message.Substring(ftpConnect.Message.IndexOf("\r\n") + 2); return this.GetList(ftpConnect.Message); } catch (Exception ex) { throw (ex); } finally { if (socketData != null && socketData.Connected) socketData.Close(); socketData = null; if (ftpConnect != null) ftpConnect.DisConnect(); } } #region 用於得到文件列表的方法 /// <summary> /// 文件列表類型枚舉 /// </summary> private enum FileListStyle { /// <summary> /// Unix系統類型 /// </summary> UnixStyle, /// <summary> /// Windows系統類型 /// </summary> WindowsStyle, /// <summary> /// 未知類型 /// </summary> Unknown } /// <summary> /// 列出FTP服務器上面當前目錄的所有文件 /// </summary> /// <param name="listUrl">查看目標目錄</param> /// <returns>返回文件信息列表</returns> public List<FileStruct> ListFiles(string listUrl) { List<FileStruct> listFile = null; try { List<FileStruct> listAll = this.ListDirectoryDetails(listUrl); listFile = new List<FileStruct>(); foreach (FileStruct file in listAll) { if (!file.IsDirectory) { listFile.Add(file); } } } catch (Exception ex) { throw ex; } return listFile; } /// <summary> /// 列出FTP服務器上面當前目錄的所有的目錄 /// </summary> /// <param name="listUrl">查看目標目錄</param> /// <returns>返回目錄信息列表</returns> public List<FileStruct> ListDirectories(string listUrl) { List<FileStruct> listAll = this.ListDirectoryDetails(listUrl); List<FileStruct> listDirectory = new List<FileStruct>(); foreach (FileStruct file in listAll) { if (file.IsDirectory) { listDirectory.Add(file); } } return listDirectory; } /// <summary> /// 獲得文件和目錄列表 /// </summary> /// <param name="datastring">FTP返回的列表字符信息</param> private List<FileStruct> GetList(string datastring) { List<FileStruct> myListArray = new List<FileStruct>(); string[] dataRecords = datastring.Split('\n'); FileListStyle _directoryListStyle = GuessFileListStyle(dataRecords); foreach (string s in dataRecords) { if (_directoryListStyle != FileListStyle.Unknown && s != "") { FileStruct f = new FileStruct(); f.Name = ".."; switch (_directoryListStyle) { case FileListStyle.UnixStyle: f = ParseFileStructFromUnixStyleRecord(s); break; case FileListStyle.WindowsStyle: f = ParseFileStructFromWindowsStyleRecord(s); break; } if (!(f.Name == "." || f.Name == "..")) { myListArray.Add(f); } } } return myListArray; } /// <summary> /// 從Windows格式中返回文件信息 /// </summary> /// <param name="Record">文件信息</param> private FileStruct ParseFileStructFromWindowsStyleRecord(string Record) { FileStruct f = new FileStruct(); string processstr = Record.Trim(); string dateStr = processstr.Substring(0, 8); processstr = (processstr.Substring(8, processstr.Length - 8)).Trim(); string timeStr = processstr.Substring(0, 7); processstr = (processstr.Substring(7, processstr.Length - 7)).Trim(); DateTimeFormatInfo myDTFI = new CultureInfo("en-US", false).DateTimeFormat; myDTFI.ShortTimePattern = "t"; f.CreateTime = DateTime.Parse(dateStr + " " + timeStr, myDTFI); if (processstr.Substring(0, 5) == "<DIR>") { f.IsDirectory = true; processstr = (processstr.Substring(5, processstr.Length - 5)).Trim(); } else { //string[] strs = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // true); //processstr = strs[1]; processstr = processstr.Substring(processstr.IndexOf(' ') + 1); f.IsDirectory = false; } f.Name = processstr; return f; } /// <summary> /// 根據文件列表記錄猜想文件列表類型 /// </summary> /// <param name="recordList"></param> /// <returns></returns> private FileListStyle GuessFileListStyle(string[] recordList) { foreach (string s in recordList) { if (s.Length > 10 && Regex.IsMatch(s.Substring(0, 10), "(-|d)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)")) { return FileListStyle.UnixStyle; } else if (s.Length > 8 && Regex.IsMatch(s.Substring(0, 8), "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]")) { return FileListStyle.WindowsStyle; } } return FileListStyle.Unknown; } /// <summary> /// 從Unix格式中返回文件信息 /// </summary> /// <param name="Record">文件信息</param> private FileStruct ParseFileStructFromUnixStyleRecord(string Record) { FileStruct f = new FileStruct(); string processstr = Record.Trim(); f.Flags = processstr.Substring(0, 10); f.IsDirectory = (f.Flags[0] == 'd'); processstr = (processstr.Substring(11)).Trim(); _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); //跳過一部分 f.Owner = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); f.Group = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); f.FileSize = Convert.ToInt32(_cutSubstringFromStringWithTrim(ref processstr, ' ', 0)); //_cutSubstringFromStringWithTrim(ref processstr, ' ', 0); //跳過一部分 string yearOrTime = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[2]; if (yearOrTime.IndexOf(":") >= 0) //time { processstr = processstr.Replace(yearOrTime, DateTime.Now.Year.ToString()); } f.CreateTime = DateTime.Parse(_cutSubstringFromStringWithTrim(ref processstr, ' ', 8)); f.Name = processstr; //最后就是名稱 return f; } /// <summary> /// 按照一定的規則進行字符串截取 /// </summary> /// <param name="s">截取的字符串</param> /// <param name="c">查找的字符</param> /// <param name="startIndex">查找的位置</param> private string _cutSubstringFromStringWithTrim(ref string s, char c, int startIndex) { int pos1 = s.IndexOf(c, startIndex); string retString = s.Substring(0, pos1); s = (s.Substring(pos1)).Trim(); return retString; } #endregion #endregion #region 上傳文件 /// <summary> /// 直接上傳文件 /// </summary> /// <param name="uploadUrl">上傳的目標全路徑與文件名</param> /// <param name="isContinueUpload">是否斷點續傳</param> /// <returns>上傳是否成功</returns> public bool UploadFileNow(byte[] fileBytes, string uploadUrl, bool isContinueUpload) { bool result = true; FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; Socket socketData = null; int iCharIndex = 0; int bytesRead; long lOffset = 0, lTotalReaded = 0; string strDirUrl, strDirUrlTemp; try { ftpUrl = new FTPUrl(uploadUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中 #region 判斷並創建文件夾 strDirUrl = ftpUrl.SubUrl; if (strDirUrl.IndexOf("/") >= 0) strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/")); while (true && strDirUrl.Trim() != "") { iCharIndex = strDirUrl.IndexOf("/", iCharIndex) + 1; if (iCharIndex == 0) strDirUrlTemp = strDirUrl; else strDirUrlTemp = strDirUrl.Substring(0, iCharIndex); if (strDirUrlTemp == "") continue; ftpConnect.SendCommand("MKD " + strDirUrlTemp); if (ftpConnect.ReplyCode != 257 && ftpConnect.ReplyCode != 550) throw new IOException(ftpConnect.ReplyString.Substring(4)); if (strDirUrlTemp == strDirUrl) break; } #endregion ftpConnect.ChangeDir(strDirUrl); #region 得到服務器上的文件大小 if (isContinueUpload) { string strDirName = ftpUrl.SubUrl; if (strDirName.IndexOf("/") >= 0) strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/")); ftpConnect.ChangeDir(strDirName); ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl)); if (ftpConnect.ReplyCode == 213) lOffset = Int64.Parse(ftpConnect.ReplyString.Substring(4)); } #endregion #region 開始上傳 lTotalReaded = lOffset; socketData = ftpConnect.CreateDataSocket(); if (lOffset > 0) ftpConnect.SendCommand("APPE " + Path.GetFileName(uploadUrl)); else ftpConnect.SendCommand("STOR " + Path.GetFileName(uploadUrl)); if (!(ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 150)) throw new IOException(ftpConnect.ReplyString.Substring(4)); ftpConnect.DataTransmitting = true; while (true) { if (!ftpConnect.DataTransmitting) { this.OnFileUploadCanceled(ftpConnect); break; } this.OnFileUploading(ftpConnect, fileBytes.Length, lTotalReaded); //開始上傳資料 bytesRead = (int)((fileBytes.Length > lTotalReaded + ftpConnect.Buffer.Length) ? ftpConnect.Buffer.Length : (fileBytes.Length - lTotalReaded)); if (bytesRead == 0) break; Array.Copy(fileBytes, lTotalReaded, ftpConnect.Buffer, 0, bytesRead); socketData.Send(ftpConnect.Buffer, bytesRead, 0); lTotalReaded += bytesRead; } if (socketData.Connected) socketData.Close(); if (ftpConnect.DataTransmitting) { if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) { ftpConnect.ReadReply(); if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) throw new IOException(ftpConnect.ReplyString.Substring(4)); } this.OnFileUploadCompleted(ftpConnect); } #endregion } catch (Exception ex) { result = false; throw (ex); } finally { if (socketData != null && socketData.Connected) socketData.Close(); if (ftpConnect != null) { ftpConnect.DisConnect(); this.m_FTPConnectList.Remove(ftpConnect); } } return result; } /// <summary> /// 直接上傳文件 /// </summary> /// <param name="filePath">上傳文件的全路徑</param> /// <param name="uploadUrl">上傳的目標全路徑與文件名</param> /// <param name="isContinueUpload">是否斷點續傳</param> /// <returns>上傳是否成功</returns> public bool UploadFileNow(string filePath, string uploadUrl, bool isContinueUpload) { bool result = true; FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; Socket socketData = null; FileStream fileStream = null; int iCharIndex = 0; int bytesRead; long lOffset = 0, lTotalReaded = 0; string strDirUrl, strDirUrlTemp; try { ftpUrl = new FTPUrl(uploadUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中 #region 判斷並創建文件夾 strDirUrl = ftpUrl.SubUrl; if (strDirUrl.IndexOf("/") >= 0) strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/")); while (true && strDirUrl.Trim() != "") { iCharIndex = strDirUrl.IndexOf("/", iCharIndex) + 1; if (iCharIndex == 0) strDirUrlTemp = strDirUrl; else strDirUrlTemp = strDirUrl.Substring(0, iCharIndex); if (strDirUrlTemp == "") continue; ftpConnect.SendCommand("MKD " + strDirUrlTemp); if (ftpConnect.ReplyCode != 257 && ftpConnect.ReplyCode != 550) throw new IOException(ftpConnect.ReplyString.Substring(4)); if (strDirUrlTemp == strDirUrl) break; } #endregion ftpConnect.ChangeDir(strDirUrl); #region 得到服務器上的文件大小 if (isContinueUpload) { string strDirName = ftpUrl.SubUrl; if (strDirName.IndexOf("/") >= 0) strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/")); ftpConnect.ChangeDir(strDirName); ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl)); if (ftpConnect.ReplyCode == 213) lOffset = Int64.Parse(ftpConnect.ReplyString.Substring(4)); } #endregion #region 開始上傳 fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); lTotalReaded = lOffset; fileStream.Seek(lOffset, SeekOrigin.Begin); socketData = ftpConnect.CreateDataSocket(); if (lOffset > 0) ftpConnect.SendCommand("APPE " + Path.GetFileName(filePath)); else ftpConnect.SendCommand("STOR " + Path.GetFileName(filePath)); if (!(ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 150)) throw new IOException(ftpConnect.ReplyString.Substring(4)); ftpConnect.DataTransmitting = true; while (true) { if (!ftpConnect.DataTransmitting) { this.OnFileUploadCanceled(ftpConnect); break; } this.OnFileUploading(ftpConnect, fileStream.Length, lTotalReaded); //開始上傳資料 bytesRead = fileStream.Read(ftpConnect.Buffer, 0, ftpConnect.Buffer.Length); if (bytesRead == 0) break; socketData.Send(ftpConnect.Buffer, bytesRead, 0); lTotalReaded += bytesRead; } fileStream.Close(); if (socketData.Connected) socketData.Close(); if (ftpConnect.DataTransmitting) { if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) { ftpConnect.ReadReply(); if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) throw new IOException(ftpConnect.ReplyString.Substring(4)); } this.OnFileUploadCompleted(ftpConnect); } #endregion } catch (Exception ex) { result = false; throw (ex); } finally { if (fileStream != null) fileStream.Close(); if (socketData != null && socketData.Connected) socketData.Close(); if (ftpConnect != null) { ftpConnect.DisConnect(); this.m_FTPConnectList.Remove(ftpConnect); } } return result; } /// <summary> /// 上傳文件 /// </summary> /// <param name="filePath"></param> /// <param name="uploadUrl"></param> public string UploadFile(string filePath, string uploadUrl) { return this.UploadFile(filePath, uploadUrl, false); } /// <summary> /// 上傳文件 /// </summary> /// <param name="filePath">上傳文件的全路徑</param> /// <param name="uploadUrl">上傳的目標全路徑 包含了用戶名用戶密碼與文件名</param> /// <param name="isContinueUpload">是否斷點續傳</param> /// <returns>返回控制上傳下載的ID</returns> public string UploadFile(string filePath, string uploadUrl, bool isContinueUpload) { String strFTPId = System.Guid.NewGuid().ToString(); IList<object> objList = new List<object> { filePath, uploadUrl, isContinueUpload, strFTPId }; System.Threading.Thread threadUpload = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(ThreadUploadFile)); threadUpload.Start(objList); //開始采用線程方式下載 return strFTPId; } /// <summary> /// 線程接收上傳 /// </summary> /// <param name="obj"></param> private void ThreadUploadFile(object obj) { string filePath; string uploadUrl; bool isContinueUpload; string strFTPId; IList<object> objList = obj as IList<object>; if (objList != null && objList.Count == 4) { filePath = objList[0] as string; uploadUrl = objList[1] as string; isContinueUpload = (bool)objList[2]; strFTPId = objList[3] as string; this.ThreadUploadFile(filePath, uploadUrl, isContinueUpload, strFTPId); } } /// <summary> /// 線程上傳文件 /// </summary> /// <param name="filePath">上傳文件的全路徑</param> /// <param name="uploadUrl">上傳的目標全路徑與文件名</param> /// <param name="isContinueUpload">是否斷點續傳</param> /// <returns>上傳是否成功</returns> private bool ThreadUploadFile(string filePath, string uploadUrl, bool isContinueUpload, string strFTPId) { bool result = true; FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; Socket socketData = null; FileStream fileStream = null; int iCharIndex = 0; int bytesRead; long lOffset = 0, lTotalReaded = 0; string strDirUrl, strDirUrlTemp; try { ftpUrl = new FTPUrl(uploadUrl); ftpConnect = new FTPConnect(ftpUrl, strFTPId); ftpConnect.Connect(); this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中 #region 判斷並創建文件夾 strDirUrl = ftpUrl.SubUrl; if (strDirUrl.IndexOf("/") >= 0) strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/")); while (true && strDirUrl.Trim() != "") { iCharIndex = strDirUrl.IndexOf("/", iCharIndex) + 1; if (iCharIndex == 0) strDirUrlTemp = strDirUrl; else strDirUrlTemp = strDirUrl.Substring(0, iCharIndex); if (strDirUrlTemp == "") continue; ftpConnect.SendCommand("MKD " + strDirUrlTemp); if (ftpConnect.ReplyCode != 257 && ftpConnect.ReplyCode != 550) throw new IOException(ftpConnect.ReplyString.Substring(4)); if (strDirUrlTemp == strDirUrl) break; } #endregion ftpConnect.ChangeDir(strDirUrl); #region 得到服務器上的文件大小 if (isContinueUpload) { string strDirName = ftpUrl.SubUrl; if (strDirName.IndexOf("/") >= 0) strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/")); ftpConnect.ChangeDir(strDirName); ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl)); if (ftpConnect.ReplyCode == 213) lOffset = Int64.Parse(ftpConnect.ReplyString.Substring(4)); } #endregion #region 開始上傳 fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); lTotalReaded = lOffset; fileStream.Seek(lOffset, SeekOrigin.Begin); socketData = ftpConnect.CreateDataSocket(); if (lOffset > 0) ftpConnect.SendCommand("APPE " + Path.GetFileName(uploadUrl)); else ftpConnect.SendCommand("STOR " + Path.GetFileName(uploadUrl)); if (!(ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 150)) throw new IOException(ftpConnect.ReplyString.Substring(4)); ftpConnect.DataTransmitting = true; while (true) { if (!ftpConnect.DataTransmitting) { this.OnFileUploadCanceled(ftpConnect); break; } this.OnFileUploading(ftpConnect, fileStream.Length, lTotalReaded); //開始上傳資料 bytesRead = fileStream.Read(ftpConnect.Buffer, 0, ftpConnect.Buffer.Length); if (bytesRead == 0) break; socketData.Send(ftpConnect.Buffer, bytesRead, 0); lTotalReaded += bytesRead; } fileStream.Close(); if (socketData.Connected) socketData.Close(); if (ftpConnect.DataTransmitting) { if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) { ftpConnect.ReadReply(); if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) throw new IOException(ftpConnect.ReplyString.Substring(4)); } this.OnFileUploadCompleted(ftpConnect); } #endregion } catch (Exception ex) { result = false; this.OnFtpError(ftpConnect, ex); } finally { if (fileStream != null) fileStream.Close(); if (socketData != null && socketData.Connected) socketData.Close(); if (ftpConnect != null) { ftpConnect.DisConnect(); this.m_FTPConnectList.Remove(ftpConnect); } } return result; } /// <summary> /// 取消正在上傳的文件 /// </summary> /// <returns></returns> public void CancelUploadFile(FTPConnect ftpConnect) { if (ftpConnect != null) ftpConnect.DataTransmitting = false; } /// <summary> /// 取消正在上傳的文件 /// </summary> /// <param name="strID"></param> public void CancelUploadFile(string strID) { foreach (FTPConnect ftp in this.m_FTPConnectList) { if (ftp != null && ftp.ID == strID) { ftp.DataTransmitting = false; break; } } } #endregion #region 下載文件 /// <summary> /// 直接下載文件 /// </summary> /// <param name="downloadUrl">要下載文件的路徑</param> /// <param name="fileBytes">存貯的內容</param> /// <returns>下載是否成功</returns> public bool DownloadFileNow(string downloadUrl, out byte[] fileBytes) { bool result = true; FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; Socket socketData = null; fileBytes = new byte[] { }; int bytesRead; long lTotalReaded = 0, lFileSize; try { ftpUrl = new FTPUrl(downloadUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中 string strDirUrl = ftpUrl.SubUrl; if (strDirUrl.IndexOf("/") >= 0) strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/")); ftpConnect.ChangeDir(strDirUrl); #region 得到服務器上的文件大小 string strDirName = ftpUrl.SubUrl; if (strDirName.IndexOf("/") >= 0) strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/")); ftpConnect.ChangeDir(strDirName); ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl)); if (ftpConnect.ReplyCode == 213) lFileSize = Int64.Parse(ftpConnect.ReplyString.Substring(4)); else throw new IOException(ftpConnect.ReplyString.Substring(4)); #endregion socketData = ftpConnect.CreateDataSocket(); fileBytes = new byte[lFileSize]; ftpConnect.SendCommand("RETR " + Path.GetFileName(ftpUrl.SubUrl)); if (!(ftpConnect.ReplyCode == 150 || ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) throw new IOException(ftpConnect.ReplyString.Substring(4)); #region 開始下載 ftpConnect.DataTransmitting = true; while (true) { if (!ftpConnect.DataTransmitting) //判斷取消是否取消了下載 { this.OnFileDownloadCanceled(ftpConnect); break; } this.OnFileDownloading(ftpConnect, lFileSize, lTotalReaded); //開始將文件流寫入本地 bytesRead = socketData.Receive(ftpConnect.Buffer, ftpConnect.Buffer.Length, 0); if (bytesRead <= 0) break; Array.Copy(ftpConnect.Buffer, 0, fileBytes, lTotalReaded, bytesRead); lTotalReaded += bytesRead; } if (socketData.Connected) socketData.Close(); if (ftpConnect.DataTransmitting) { if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) { ftpConnect.ReadReply(); if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) throw new IOException(ftpConnect.ReplyString.Substring(4)); } this.OnFileDownloadCompleted(ftpConnect); } #endregion } catch (Exception ex) { result = false; throw (ex); } finally { if (socketData != null && socketData.Connected) socketData.Close(); if (ftpConnect != null) { ftpConnect.DisConnect(); this.m_FTPConnectList.Remove(ftpConnect); } } return result; } /// <summary> /// 直接下載文件 /// </summary> /// <param name="downloadUrl">要下載文件的路徑</param> /// <param name="targetFile">目標存在全路徑</param> /// <param name="isContinueDownload">是否斷點續傳</param> /// <returns>下載是否成功</returns> public bool DownloadFileNow(string downloadUrl, string targetFile, bool isContinueDownload) { bool result = true; FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; Socket socketData = null; FileStream fileStream = null; int bytesRead; long lTotalReaded = 0, lFileSize; try { ftpUrl = new FTPUrl(downloadUrl); ftpConnect = new FTPConnect(ftpUrl); ftpConnect.Connect(); this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中 string strDirUrl = ftpUrl.SubUrl; if (strDirUrl.IndexOf("/") >= 0) strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/")); ftpConnect.ChangeDir(strDirUrl); #region 得到服務器上的文件大小 string strDirName = ftpUrl.SubUrl; if (strDirName.IndexOf("/") >= 0) strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/")); ftpConnect.ChangeDir(strDirName); ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl)); if (ftpConnect.ReplyCode == 213) lFileSize = Int64.Parse(ftpConnect.ReplyString.Substring(4)); else throw new IOException(ftpConnect.ReplyString.Substring(4)); #endregion socketData = ftpConnect.CreateDataSocket(); //斷點續傳長度的偏移量 if (System.IO.File.Exists(targetFile) && isContinueDownload) { System.IO.FileInfo fiInfo = new FileInfo(targetFile); lTotalReaded = fiInfo.Length; ftpConnect.SendCommand("REST " + fiInfo.Length.ToString()); if (ftpConnect.ReplyCode != 350) throw new IOException(ftpConnect.ReplyString.Substring(4)); } ftpConnect.SendCommand("RETR " + Path.GetFileName(ftpUrl.SubUrl)); if (!(ftpConnect.ReplyCode == 150 || ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) throw new IOException(ftpConnect.ReplyString.Substring(4)); #region 開始下載 string strTargetPath = targetFile; strTargetPath = strTargetPath.Substring(0, strTargetPath.LastIndexOf("\\"));//這里本來是// if (!System.IO.Directory.Exists(strTargetPath)) //判斷目標路徑是否存在,如果不存在就創建 System.IO.Directory.CreateDirectory(strTargetPath); if (System.IO.File.Exists(targetFile) && isContinueDownload) //目標文件已經是全路徑了 斷點續傳 fileStream = new System.IO.FileStream(targetFile, System.IO.FileMode.Append, System.IO.FileAccess.Write); else fileStream = new System.IO.FileStream(targetFile, System.IO.FileMode.Create, System.IO.FileAccess.Write); ftpConnect.DataTransmitting = true; while (true) { if (!ftpConnect.DataTransmitting) //判斷取消是否取消了下載 { this.OnFileDownloadCanceled(ftpConnect); break; } this.OnFileDownloading(ftpConnect, lFileSize, lTotalReaded); //開始將文件流寫入本地 bytesRead = socketData.Receive(ftpConnect.Buffer, ftpConnect.Buffer.Length, 0); if (bytesRead <= 0) break; fileStream.Write(ftpConnect.Buffer, 0, bytesRead); lTotalReaded += bytesRead; } fileStream.Close(); if (socketData.Connected) socketData.Close(); if (ftpConnect.DataTransmitting) { if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) { ftpConnect.ReadReply(); if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) throw new IOException(ftpConnect.ReplyString.Substring(4)); } this.OnFileDownloadCompleted(ftpConnect); } #endregion } catch (Exception ex) { result = false; throw (ex); } finally { if (fileStream != null) fileStream.Close(); if (socketData != null && socketData.Connected) socketData.Close(); if (ftpConnect != null) { ftpConnect.DisConnect(); this.m_FTPConnectList.Remove(ftpConnect); } } return result; } /// <summary> /// 下載文件 /// </summary> /// <param name="downloadUrl"></param> /// <param name="targetFile"></param> public string DownloadFile(string downloadUrl, string targetFile) { return this.DownloadFile(downloadUrl, targetFile, false); } /// <summary> /// 下載文件 /// </summary> /// <param name="downloadUrl">要下載文件的路徑 包含了登錄名與登錄密碼</param> /// <param name="TargetFile">目標存在路徑包含文件名</param> /// <param name="isContinueDownload">是否斷點續傳</param> /// <returns>返回下載控制ID</returns> public string DownloadFile(string downloadUrl, string targetFile, bool isContinueDownload) { String strFTPId = System.Guid.NewGuid().ToString(); IList<object> objList = new List<object> { downloadUrl, targetFile, isContinueDownload, strFTPId }; System.Threading.Thread threadDownload = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(ThreadDownloadFile)); threadDownload.Start(objList); //開始采用線程方式下載 return strFTPId; } /// <summary> /// 線程接收下載 /// </summary> /// <param name="obj"></param> private void ThreadDownloadFile(object obj) { string downloadUrl; string targetFile; bool isContinueDownload; string strFTPId; IList<object> objList = obj as IList<object>; if (objList != null && objList.Count == 4) { downloadUrl = objList[0] as string; targetFile = objList[1] as string; isContinueDownload = (bool)objList[2]; strFTPId = objList[3] as String; this.ThreadDownloadFile(downloadUrl, targetFile, isContinueDownload, strFTPId); } } /// <summary> /// 線程下載文件 /// </summary> /// <param name="downloadUrl">要下載文件的路徑</param> /// <param name="targetFile">目標存在全路徑</param> /// <param name="isContinueDownload">是否斷點續傳</param> /// <returns>下載是否成功</returns> private bool ThreadDownloadFile(string downloadUrl, string targetFile, bool isContinueDownload, string strFTPId) { bool result = true; FTPUrl ftpUrl = null; FTPConnect ftpConnect = null; Socket socketData = null; FileStream fileStream = null; int bytesRead; long lTotalReaded = 0, lFileSize; try { ftpUrl = new FTPUrl(downloadUrl); ftpConnect = new FTPConnect(ftpUrl, strFTPId); ftpConnect.Connect(); this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中 string strDirUrl = ftpUrl.SubUrl; if (strDirUrl.IndexOf("/") >= 0) strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/")); ftpConnect.ChangeDir(strDirUrl); #region 得到服務器上的文件大小 string strDirName = ftpUrl.SubUrl; if (strDirName.IndexOf("/") >= 0) strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/")); ftpConnect.ChangeDir(strDirName); ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl)); if (ftpConnect.ReplyCode == 213) lFileSize = Int64.Parse(ftpConnect.ReplyString.Substring(4)); else throw new IOException(ftpConnect.ReplyString.Substring(4)); #endregion socketData = ftpConnect.CreateDataSocket(); //斷點續傳長度的偏移量 if (System.IO.File.Exists(targetFile) && isContinueDownload) { System.IO.FileInfo fiInfo = new FileInfo(targetFile); lTotalReaded = fiInfo.Length; ftpConnect.SendCommand("REST " + fiInfo.Length.ToString()); if (ftpConnect.ReplyCode != 350) throw new IOException(ftpConnect.ReplyString.Substring(4)); } ftpConnect.SendCommand("RETR " + Path.GetFileName(ftpUrl.SubUrl)); if (!(ftpConnect.ReplyCode == 150 || ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) throw new IOException(ftpConnect.ReplyString.Substring(4)); #region 開始下載 string strTargetPath = targetFile; strTargetPath = strTargetPath.Substring(0, strTargetPath.LastIndexOf("//")); if (!System.IO.Directory.Exists(strTargetPath)) //判斷目標路徑是否存在,如果不存在就創建 System.IO.Directory.CreateDirectory(strTargetPath); if (System.IO.File.Exists(targetFile) && isContinueDownload) //目標文件已經是全路徑了 斷點續傳 fileStream = new System.IO.FileStream(targetFile, System.IO.FileMode.Append, System.IO.FileAccess.Write); else fileStream = new System.IO.FileStream(targetFile, System.IO.FileMode.Create, System.IO.FileAccess.Write); ftpConnect.DataTransmitting = true; while (true) { if (!ftpConnect.DataTransmitting) //判斷取消是否取消了下載 { this.OnFileDownloadCanceled(ftpConnect); break; } this.OnFileDownloading(ftpConnect, lFileSize, lTotalReaded); //開始將文件流寫入本地 bytesRead = socketData.Receive(ftpConnect.Buffer, ftpConnect.Buffer.Length, 0); if (bytesRead <= 0) break; fileStream.Write(ftpConnect.Buffer, 0, bytesRead); lTotalReaded += bytesRead; } fileStream.Close(); if (socketData.Connected) socketData.Close(); if (ftpConnect.DataTransmitting) { if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) { ftpConnect.ReadReply(); if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250)) throw new IOException(ftpConnect.ReplyString.Substring(4)); } this.OnFileDownloadCompleted(ftpConnect); } #endregion } catch (Exception ex) { result = false; this.OnFtpError(ftpConnect, ex); } finally { if (fileStream != null) fileStream.Close(); if (socketData != null && socketData.Connected) socketData.Close(); if (ftpConnect != null) { ftpConnect.DisConnect(); this.m_FTPConnectList.Remove(ftpConnect); } } return result; } /// <summary> /// 取消正在下載的文件 /// </summary> /// <returns></returns> public void CancelDownloadFile(FTPConnect ftpConnect) { if (ftpConnect != null) ftpConnect.DataTransmitting = false; } /// <summary> /// 取消正在下載的文件 /// </summary> /// <param name="strID"></param> public void CancelDownloadFile(string strID) { foreach (FTPConnect ftp in this.m_FTPConnectList) { if (ftp != null && ftp.ID == strID) { ftp.DataTransmitting = false; break; } } } #endregion #region 根據指定的ID查找FTPConnect /// <summary> /// 根據指定的ID查找FTPConnect /// </summary> /// <param name="id"></param> /// <returns></returns> public FTPConnect FindFTPConnectByID(string id) { foreach (FTPConnect ftpConnect in this.m_FTPConnectList) { if (ftpConnect != null && ftpConnect.ID == id) return ftpConnect; } return null; } #endregion #region 傳輸類型 public enum FTPType { /// <summary> /// 無狀態 /// </summary> None, /// <summary> /// 上傳 /// </summary> Upload, /// <summary> /// 下載 /// </summary> Download } #endregion } #region 文件信息結構 public struct FileStruct { public string Flags; public string Owner; public string Group; public int FileSize; public bool IsDirectory; public DateTime CreateTime; public string Name; } #endregion #region 文件傳輸進度控制事件 public delegate void FTPSendEventHandler(object sender, FTPSendEventArgs e); public class FTPSendEventArgs : System.EventArgs { private long m_totalbytes; // Total Bytes private long m_bytestransfered; public FTPSendEventArgs() { m_totalbytes = 0; m_bytestransfered = 0; } public FTPSendEventArgs(long lTotalBytes, long lBytesTransfered) { m_totalbytes = lTotalBytes; m_bytestransfered = lBytesTransfered; } /// <summary> /// 總字節數 /// </summary> public long TotalBytes { get { return m_totalbytes; } set { m_totalbytes = value; } } /// <summary> /// 已傳輸字節數 /// </summary> public long BytesTransfered { get { return m_bytestransfered; } set { m_bytestransfered = value; } } } public delegate void FTPErrorEventHandler(object sender, FTPErrorEventArgs e); public class FTPErrorEventArgs : System.EventArgs { private Exception m_Error = null; public FTPErrorEventArgs() { } public FTPErrorEventArgs(Exception error) { this.m_Error = error; } /// <summary> /// 錯誤消息 /// </summary> public Exception Error { get { return this.m_Error; } set { this.m_Error = value; } } } #endregion }
使用示例:
private void Download() { FTPHelper ftphelper = new FTPHelper(); ftphelper.FileDownloading += new FTPSendEventHandler(ftphelper_FileDownloading); ftphelper.FileDownloadCompleted += new EventHandler(ftphelper_FileDownloadCompleted); ftphelper.DownloadFileNow("ftp://userName:password@address/test.mp3", "D://office//test.mp3", false); } private void ftphelper_FileDownloadCompleted(object sender, EventArgs e) { MessageBox.Show("下載完成"); } private void ftphelper_FileDownloading(object sender, FTPSendEventArgs e) { progressBar.Maximum = (int)e.TotalBytes; progressBar.Value = ((int)e.BytesTransfered); }
使用WebRequest的另一個Ftp類:
using System; using System.Collections.Generic; using System.Text; using System.Net; using System.IO; using System.Globalization; using System.Text.RegularExpressions; namespace Ftp { #region 文件信息結構 public struct FileStruct { public string Flags; public string Owner; public string Group; public bool IsDirectory; public DateTime CreateTime; public string Name; } public enum FileListStyle { UnixStyle, WindowsStyle, Unknown } #endregion /// <summary> /// FTP處理操作類 /// 功能: /// 下載文件 /// 上傳文件 /// 上傳文件的進度信息 /// 下載文件的進度信息 /// 刪除文件 /// 列出文件 /// 列出目錄 /// 進入子目錄 /// 退出當前目錄返回上一層目錄 /// 判斷遠程文件是否存在 /// 判斷遠程文件是否存在 /// 刪除遠程文件 /// 建立目錄 /// 刪除目錄 /// 文件(目錄)改名 /// </summary> public class FTPHelper { #region 屬性信息 /// <summary> /// FTP請求對象 /// </summary> FtpWebRequest Request = null; /// <summary> /// FTP響應對象 /// </summary> FtpWebResponse Response = null; /// <summary> /// FTP服務器地址 /// </summary> private Uri _Uri; /// <summary> /// FTP服務器地址 /// </summary> public Uri Uri { get { if (_DirectoryPath == "/") { return _Uri; } else { string strUri = _Uri.ToString(); if (strUri.EndsWith("/")) { strUri = strUri.Substring(0, strUri.Length - 1); } return new Uri(strUri + this.DirectoryPath); } } set { if (value.Scheme != Uri.UriSchemeFtp) { throw new Exception("Ftp 地址格式錯誤!"); } _Uri = new Uri(value.GetLeftPart(UriPartial.Authority)); _DirectoryPath = value.AbsolutePath; if (!_DirectoryPath.EndsWith("/")) { _DirectoryPath += "/"; } } } /// <summary> /// 當前工作目錄 /// </summary> private string _DirectoryPath; /// <summary> /// 當前工作目錄 /// </summary> public string DirectoryPath { get { return _DirectoryPath; } set { _DirectoryPath = value; } } /// <summary> /// FTP登錄用戶 /// </summary> private string _UserName; /// <summary> /// FTP登錄用戶 /// </summary> public string UserName { get { return _UserName; } set { _UserName = value; } } /// <summary> /// 錯誤信息 /// </summary> private string _ErrorMsg; /// <summary> /// 錯誤信息 /// </summary> public string ErrorMsg { get { return _ErrorMsg; } set { _ErrorMsg = value; } } /// <summary> /// FTP登錄密碼 /// </summary> private string _Password; /// <summary> /// FTP登錄密碼 /// </summary> public string Password { get { return _Password; } set { _Password = value; } } /// <summary> /// 連接FTP服務器的代理服務 /// </summary> private WebProxy _Proxy = null; /// <summary> /// 連接FTP服務器的代理服務 /// </summary> public WebProxy Proxy { get { return _Proxy; } set { _Proxy = value; } } /// <summary> /// 是否需要刪除臨時文件 /// </summary> private bool _isDeleteTempFile = false; /// <summary> /// 異步上傳所臨時生成的文件 /// </summary> private string _UploadTempFile = ""; #endregion #region 事件 public delegate void De_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e); public delegate void De_DownloadDataCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e); public delegate void De_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e); public delegate void De_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e); /// <summary> /// 異步下載進度發生改變觸發的事件 /// </summary> public event De_DownloadProgressChanged DownloadProgressChanged; /// <summary> /// 異步下載文件完成之后觸發的事件 /// </summary> public event De_DownloadDataCompleted DownloadDataCompleted; /// <summary> /// 異步上傳進度發生改變觸發的事件 /// </summary> public event De_UploadProgressChanged UploadProgressChanged; /// <summary> /// 異步上傳文件完成之后觸發的事件 /// </summary> public event De_UploadFileCompleted UploadFileCompleted; #endregion #region 構造析構函數 /// <summary> /// 構造函數 /// </summary> /// <param name="FtpUri">FTP地址</param> /// <param name="strUserName">登錄用戶名</param> /// <param name="strPassword">登錄密碼</param> public FTPHelper(Uri FtpUri, string strUserName, string strPassword) { this._Uri = new Uri(FtpUri.GetLeftPart(UriPartial.Authority)); _DirectoryPath = FtpUri.AbsolutePath; if (!_DirectoryPath.EndsWith("/")) { _DirectoryPath += "/"; } this._UserName = strUserName; this._Password = strPassword; this._Proxy = null; } /// <summary> /// 構造函數 /// </summary> /// <param name="FtpUri">FTP地址</param> /// <param name="strUserName">登錄用戶名</param> /// <param name="strPassword">登錄密碼</param> /// <param name="objProxy">連接代理</param> public FTPHelper(Uri FtpUri, string strUserName, string strPassword, WebProxy objProxy) { this._Uri = new Uri(FtpUri.GetLeftPart(UriPartial.Authority)); _DirectoryPath = FtpUri.AbsolutePath; if (!_DirectoryPath.EndsWith("/")) { _DirectoryPath += "/"; } this._UserName = strUserName; this._Password = strPassword; this._Proxy = objProxy; } /// <summary> /// 構造函數 /// </summary> public FTPHelper() { this._UserName = "anonymous"; //匿名用戶 this._Password = "@anonymous"; this._Uri = null; this._Proxy = null; } /// <summary> /// 析構函數 /// </summary> ~FTPHelper() { if (Response != null) { Response.Close(); Response = null; } if (Request != null) { Request.Abort(); Request = null; } } #endregion #region 建立連接 /// <summary> /// 建立FTP鏈接,返回響應對象 /// </summary> /// <param name="uri">FTP地址</param> /// <param name="FtpMathod">操作命令</param> private FtpWebResponse Open(Uri uri, string FtpMathod) { try { Request = (FtpWebRequest)WebRequest.Create(uri); Request.Method = FtpMathod; Request.UseBinary = true; Request.KeepAlive = false; Request.Credentials = new NetworkCredential(this.UserName, this.Password); if (this.Proxy != null) { Request.Proxy = this.Proxy; } return (FtpWebResponse)Request.GetResponse(); } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 建立FTP鏈接,返回請求對象 /// </summary> /// <param name="uri">FTP地址</param> /// <param name="FtpMathod">操作命令</param> private FtpWebRequest OpenRequest(Uri uri, string FtpMathod) { try { Request = (FtpWebRequest)WebRequest.Create(uri); Request.Method = FtpMathod; Request.UseBinary = true; Request.KeepAlive = false; Request.Credentials = new NetworkCredential(this.UserName, this.Password); if (this.Proxy != null) { Request.Proxy = this.Proxy; } return Request; } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } #endregion #region 下載文件 /// <summary> /// 從FTP服務器下載文件,使用與遠程文件同名的文件名來保存文件 /// </summary> /// <param name="RemoteFileName">遠程文件名</param> /// <param name="LocalPath">本地路徑</param> public bool DownloadFile(string RemoteFileName, string LocalPath) { return DownloadFile(RemoteFileName, LocalPath, RemoteFileName); } /// <summary> /// 從FTP服務器下載文件,指定本地路徑和本地文件名 /// </summary> /// <param name="RemoteFileName">遠程文件名</param> /// <param name="LocalPath">本地路徑</param> /// <param name="LocalFilePath">保存文件的本地路徑,后面帶有"\"</param> /// <param name="LocalFileName">保存本地的文件名</param> public bool DownloadFile(string RemoteFileName, string LocalPath, string LocalFileName) { byte[] bt = null; try { if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(LocalFileName) || !IsValidPathChars(LocalPath)) { throw new Exception("非法文件名或目錄名!"); } if (!Directory.Exists(LocalPath)) { throw new Exception("本地文件路徑不存在!"); } string LocalFullPath = Path.Combine(LocalPath, LocalFileName); if (File.Exists(LocalFullPath)) { throw new Exception("當前路徑下已經存在同名文件!"); } bt = DownloadFile(RemoteFileName); if (bt != null) { FileStream stream = new FileStream(LocalFullPath, FileMode.Create); stream.Write(bt, 0, bt.Length); stream.Flush(); stream.Close(); return true; } else { return false; } } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 從FTP服務器下載文件,返回文件二進制數據 /// </summary> /// <param name="RemoteFileName">遠程文件名</param> public byte[] DownloadFile(string RemoteFileName) { try { if (!IsValidFileChars(RemoteFileName)) { throw new Exception("非法文件名或目錄名!"); } Response = Open(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.DownloadFile); Stream Reader = Response.GetResponseStream(); MemoryStream mem = new MemoryStream(1024 * 500); byte[] buffer = new byte[1024]; int bytesRead = 0; int TotalByteRead = 0; while (true) { bytesRead = Reader.Read(buffer, 0, buffer.Length); TotalByteRead += bytesRead; if (bytesRead == 0) break; mem.Write(buffer, 0, bytesRead); } if (mem.Length >= 0) { return mem.ToArray(); } else { return null; } } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } #endregion #region 異步下載文件 /// <summary> /// 從FTP服務器異步下載文件,指定本地路徑和本地文件名 /// </summary> /// <param name="RemoteFileName">遠程文件名</param> /// <param name="LocalPath">保存文件的本地路徑,后面帶有"\"</param> /// <param name="LocalFileName">保存本地的文件名</param> public void DownloadFileAsync(string RemoteFileName, string LocalPath, string LocalFileName) { //byte[] bt = null; try { if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(LocalFileName) || !IsValidPathChars(LocalPath)) { throw new Exception("非法文件名或目錄名!"); } if (!Directory.Exists(LocalPath)) { throw new Exception("本地文件路徑不存在!"); } string LocalFullPath = Path.Combine(LocalPath, LocalFileName); if (File.Exists(LocalFullPath)) { throw new Exception("當前路徑下已經存在同名文件!"); } DownloadFileAsync(RemoteFileName, LocalFullPath); } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 從FTP服務器異步下載文件,指定本地完整路徑文件名 /// </summary> /// <param name="RemoteFileName">遠程文件名</param> /// <param name="LocalFullPath">本地完整路徑文件名</param> public void DownloadFileAsync(string RemoteFileName, string LocalFullPath) { try { if (!IsValidFileChars(RemoteFileName)) { throw new Exception("非法文件名或目錄名!"); } if (File.Exists(LocalFullPath)) { throw new Exception("當前路徑下已經存在同名文件!"); } MyWebClient client = new MyWebClient(); client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged); client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(client_DownloadFileCompleted); client.Credentials = new NetworkCredential(this.UserName, this.Password); if (this.Proxy != null) { client.Proxy = this.Proxy; } client.DownloadFileAsync(new Uri(this.Uri.ToString() + RemoteFileName), LocalFullPath); } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 異步下載文件完成之后觸發的事件 /// </summary> /// <param name="sender">下載對象</param> /// <param name="e">數據信息對象</param> void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { if (DownloadDataCompleted != null) { DownloadDataCompleted(sender, e); } } /// <summary> /// 異步下載進度發生改變觸發的事件 /// </summary> /// <param name="sender">下載對象</param> /// <param name="e">進度信息對象</param> void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { if (DownloadProgressChanged != null) { DownloadProgressChanged(sender, e); } } #endregion #region 上傳文件 /// <summary> /// 上傳文件到FTP服務器 /// </summary> /// <param name="LocalFullPath">本地帶有完整路徑的文件名</param> public bool UploadFile(string LocalFullPath) { return UploadFile(LocalFullPath, Path.GetFileName(LocalFullPath), false); } /// <summary> /// 上傳文件到FTP服務器 /// </summary> /// <param name="LocalFullPath">本地帶有完整路徑的文件</param> /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param> public bool UploadFile(string LocalFullPath, bool OverWriteRemoteFile) { return UploadFile(LocalFullPath, Path.GetFileName(LocalFullPath), OverWriteRemoteFile); } /// <summary> /// 上傳文件到FTP服務器 /// </summary> /// <param name="LocalFullPath">本地帶有完整路徑的文件</param> /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param> public bool UploadFile(string LocalFullPath, string RemoteFileName) { return UploadFile(LocalFullPath, RemoteFileName, false); } /// <summary> /// 上傳文件到FTP服務器 /// </summary> /// <param name="LocalFullPath">本地帶有完整路徑的文件名</param> /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param> /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param> public bool UploadFile(string LocalFullPath, string RemoteFileName, bool OverWriteRemoteFile) { try { if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(Path.GetFileName(LocalFullPath)) || !IsValidPathChars(Path.GetDirectoryName(LocalFullPath))) { throw new Exception("非法文件名或目錄名!"); } if (File.Exists(LocalFullPath)) { FileStream Stream = new FileStream(LocalFullPath, FileMode.Open, FileAccess.Read); byte[] bt = new byte[Stream.Length]; Stream.Read(bt, 0, (Int32)Stream.Length); //注意,因為Int32的最大限制,最大上傳文件只能是大約2G多一點 Stream.Close(); return UploadFile(bt, RemoteFileName, OverWriteRemoteFile); } else { throw new Exception("本地文件不存在!"); } } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 上傳文件到FTP服務器 /// </summary> /// <param name="FileBytes">上傳的二進制數據</param> /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param> public bool UploadFile(byte[] FileBytes, string RemoteFileName) { if (!IsValidFileChars(RemoteFileName)) { throw new Exception("非法文件名或目錄名!"); } return UploadFile(FileBytes, RemoteFileName, false); } /// <summary> /// 上傳文件到FTP服務器 /// </summary> /// <param name="FileBytes">文件二進制內容</param> /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param> /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param> public bool UploadFile(byte[] FileBytes, string RemoteFileName, bool OverWriteRemoteFile) { try { if (!IsValidFileChars(RemoteFileName)) { throw new Exception("非法文件名!"); } if (!OverWriteRemoteFile && FileExist(RemoteFileName)) { throw new Exception("FTP服務上面已經存在同名文件!"); } OpenRequest(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.UploadFile); Stream requestStream = Request.GetRequestStream(); MemoryStream mem = new MemoryStream(FileBytes); byte[] buffer = new byte[1024]; int bytesRead = 0; int TotalRead = 0; while (true) { bytesRead = mem.Read(buffer, 0, buffer.Length); if (bytesRead == 0) break; TotalRead += bytesRead; requestStream.Write(buffer, 0, bytesRead); } requestStream.Close(); Response = (FtpWebResponse)Request.GetResponse(); mem.Close(); mem.Dispose(); FileBytes = null; return true; } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } #endregion #region 異步上傳文件 /// <summary> /// 異步上傳文件到FTP服務器 /// </summary> /// <param name="LocalFullPath">本地帶有完整路徑的文件名</param> public void UploadFileAsync(string LocalFullPath) { UploadFileAsync(LocalFullPath, Path.GetFileName(LocalFullPath), false); } /// <summary> /// 異步上傳文件到FTP服務器 /// </summary> /// <param name="LocalFullPath">本地帶有完整路徑的文件</param> /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param> public void UploadFileAsync(string LocalFullPath, bool OverWriteRemoteFile) { UploadFileAsync(LocalFullPath, Path.GetFileName(LocalFullPath), OverWriteRemoteFile); } /// <summary> /// 異步上傳文件到FTP服務器 /// </summary> /// <param name="LocalFullPath">本地帶有完整路徑的文件</param> /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param> public void UploadFileAsync(string LocalFullPath, string RemoteFileName) { UploadFileAsync(LocalFullPath, RemoteFileName, false); } /// <summary> /// 異步上傳文件到FTP服務器 /// </summary> /// <param name="LocalFullPath">本地帶有完整路徑的文件名</param> /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param> /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param> public void UploadFileAsync(string LocalFullPath, string RemoteFileName, bool OverWriteRemoteFile) { try { if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(Path.GetFileName(LocalFullPath)) || !IsValidPathChars(Path.GetDirectoryName(LocalFullPath))) { throw new Exception("非法文件名或目錄名!"); } if (!OverWriteRemoteFile && FileExist(RemoteFileName)) { throw new Exception("FTP服務上面已經存在同名文件!"); } if (File.Exists(LocalFullPath)) { MyWebClient client = new MyWebClient(); client.UploadProgressChanged += new UploadProgressChangedEventHandler(client_UploadProgressChanged); client.UploadFileCompleted += new UploadFileCompletedEventHandler(client_UploadFileCompleted); client.Credentials = new NetworkCredential(this.UserName, this.Password); if (this.Proxy != null) { client.Proxy = this.Proxy; } client.UploadFileAsync(new Uri(this.Uri.ToString() + RemoteFileName), LocalFullPath); } else { throw new Exception("本地文件不存在!"); } } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 異步上傳文件到FTP服務器 /// </summary> /// <param name="FileBytes">上傳的二進制數據</param> /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param> public void UploadFileAsync(byte[] FileBytes, string RemoteFileName) { if (!IsValidFileChars(RemoteFileName)) { throw new Exception("非法文件名或目錄名!"); } UploadFileAsync(FileBytes, RemoteFileName, false); } /// <summary> /// 異步上傳文件到FTP服務器 /// </summary> /// <param name="FileBytes">文件二進制內容</param> /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param> /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param> public void UploadFileAsync(byte[] FileBytes, string RemoteFileName, bool OverWriteRemoteFile) { try { if (!IsValidFileChars(RemoteFileName)) { throw new Exception("非法文件名!"); } if (!OverWriteRemoteFile && FileExist(RemoteFileName)) { throw new Exception("FTP服務上面已經存在同名文件!"); } string TempPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Templates); if (!TempPath.EndsWith("\\")) { TempPath += "\\"; } string TempFile = TempPath + Path.GetRandomFileName(); TempFile = Path.ChangeExtension(TempFile, Path.GetExtension(RemoteFileName)); FileStream Stream = new FileStream(TempFile, FileMode.CreateNew, FileAccess.Write); Stream.Write(FileBytes, 0, FileBytes.Length); //注意,因為Int32的最大限制,最大上傳文件只能是大約2G多一點 Stream.Flush(); Stream.Close(); Stream.Dispose(); _isDeleteTempFile = true; _UploadTempFile = TempFile; FileBytes = null; UploadFileAsync(TempFile, RemoteFileName, OverWriteRemoteFile); } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 異步上傳文件完成之后觸發的事件 /// </summary> /// <param name="sender">下載對象</param> /// <param name="e">數據信息對象</param> void client_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e) { if (_isDeleteTempFile) { if (File.Exists(_UploadTempFile)) { File.SetAttributes(_UploadTempFile, FileAttributes.Normal); File.Delete(_UploadTempFile); } _isDeleteTempFile = false; } if (UploadFileCompleted != null) { UploadFileCompleted(sender, e); } } /// <summary> /// 異步上傳進度發生改變觸發的事件 /// </summary> /// <param name="sender">下載對象</param> /// <param name="e">進度信息對象</param> void client_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e) { if (UploadProgressChanged != null) { UploadProgressChanged(sender, e); } } #endregion #region 列出目錄文件信息 /// <summary> /// 列出FTP服務器上面當前目錄的所有文件和目錄 /// </summary> public FileStruct[] ListFilesAndDirectories() { Response = Open(this.Uri, WebRequestMethods.Ftp.ListDirectoryDetails); StreamReader stream = new StreamReader(Response.GetResponseStream(), Encoding.Default); string Datastring = stream.ReadToEnd(); FileStruct[] list = GetList(Datastring); return list; } /// <summary> /// 列出FTP服務器上面當前目錄的所有文件 /// </summary> public FileStruct[] ListFiles() { FileStruct[] listAll = ListFilesAndDirectories(); List<FileStruct> listFile = new List<FileStruct>(); foreach (FileStruct file in listAll) { if (!file.IsDirectory) { listFile.Add(file); } } return listFile.ToArray(); } /// <summary> /// 列出FTP服務器上面當前目錄的所有的目錄 /// </summary> public FileStruct[] ListDirectories() { FileStruct[] listAll = ListFilesAndDirectories(); List<FileStruct> listDirectory = new List<FileStruct>(); foreach (FileStruct file in listAll) { if (file.IsDirectory) { listDirectory.Add(file); } } return listDirectory.ToArray(); } /// <summary> /// 獲得文件和目錄列表 /// </summary> /// <param name="datastring">FTP返回的列表字符信息</param> private FileStruct[] GetList(string datastring) { List<FileStruct> myListArray = new List<FileStruct>(); string[] dataRecords = datastring.Split('\n'); FileListStyle _directoryListStyle = GuessFileListStyle(dataRecords); foreach (string s in dataRecords) { if (_directoryListStyle != FileListStyle.Unknown && s != "") { FileStruct f = new FileStruct(); f.Name = ".."; switch (_directoryListStyle) { case FileListStyle.UnixStyle: f = ParseFileStructFromUnixStyleRecord(s); break; case FileListStyle.WindowsStyle: f = ParseFileStructFromWindowsStyleRecord(s); break; } if (!(f.Name == "." || f.Name == "..")) { myListArray.Add(f); } } } return myListArray.ToArray(); } /// <summary> /// 從Windows格式中返回文件信息 /// </summary> /// <param name="Record">文件信息</param> private FileStruct ParseFileStructFromWindowsStyleRecord(string Record) { FileStruct f = new FileStruct(); string processstr = Record.Trim(); string dateStr = processstr.Substring(0, 8); processstr = (processstr.Substring(8, processstr.Length - 8)).Trim(); string timeStr = processstr.Substring(0, 7); processstr = (processstr.Substring(7, processstr.Length - 7)).Trim(); DateTimeFormatInfo myDTFI = new CultureInfo("en-US", false).DateTimeFormat; myDTFI.ShortTimePattern = "t"; f.CreateTime = DateTime.Parse(dateStr + " " + timeStr, myDTFI); if (processstr.Substring(0, 5) == "<DIR>") { f.IsDirectory = true; processstr = (processstr.Substring(5, processstr.Length - 5)).Trim(); } else { string[] strs = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // true); processstr = strs[1]; f.IsDirectory = false; } f.Name = processstr; return f; } /// <summary> /// 判斷文件列表的方式Window方式還是Unix方式 /// </summary> /// <param name="recordList">文件信息列表</param> private FileListStyle GuessFileListStyle(string[] recordList) { foreach (string s in recordList) { if (s.Length > 10 && Regex.IsMatch(s.Substring(0, 10), "(-|d)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)")) { return FileListStyle.UnixStyle; } else if (s.Length > 8 && Regex.IsMatch(s.Substring(0, 8), "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]")) { return FileListStyle.WindowsStyle; } } return FileListStyle.Unknown; } /// <summary> /// 從Unix格式中返回文件信息 /// </summary> /// <param name="Record">文件信息</param> private FileStruct ParseFileStructFromUnixStyleRecord(string Record) { FileStruct f = new FileStruct(); string processstr = Record.Trim(); f.Flags = processstr.Substring(0, 10); f.IsDirectory = (f.Flags[0] == 'd'); processstr = (processstr.Substring(11)).Trim(); _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); //跳過一部分 f.Owner = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); f.Group = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); //跳過一部分 string yearOrTime = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[2]; if (yearOrTime.IndexOf(":") >= 0) //time { processstr = processstr.Replace(yearOrTime, DateTime.Now.Year.ToString()); } f.CreateTime = DateTime.Parse(_cutSubstringFromStringWithTrim(ref processstr, ' ', 8)); f.Name = processstr; //最后就是名稱 return f; } /// <summary> /// 按照一定的規則進行字符串截取 /// </summary> /// <param name="s">截取的字符串</param> /// <param name="c">查找的字符</param> /// <param name="startIndex">查找的位置</param> private string _cutSubstringFromStringWithTrim(ref string s, char c, int startIndex) { int pos1 = s.IndexOf(c, startIndex); string retString = s.Substring(0, pos1); s = (s.Substring(pos1)).Trim(); return retString; } #endregion #region 目錄或文件存在的判斷 /// <summary> /// 判斷當前目錄下指定的子目錄是否存在 /// </summary> /// <param name="RemoteDirectoryName">指定的目錄名</param> public bool DirectoryExist(string RemoteDirectoryName) { try { if (!IsValidPathChars(RemoteDirectoryName)) { throw new Exception("目錄名非法!"); } FileStruct[] listDir = ListDirectories(); foreach (FileStruct dir in listDir) { if (dir.Name == RemoteDirectoryName) { return true; } } return false; } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 判斷一個遠程文件是否存在服務器當前目錄下面 /// </summary> /// <param name="RemoteFileName">遠程文件名</param> public bool FileExist(string RemoteFileName) { try { if (!IsValidFileChars(RemoteFileName)) { throw new Exception("文件名非法!"); } FileStruct[] listFile = ListFiles(); foreach (FileStruct file in listFile) { if (file.Name == RemoteFileName) { return true; } } return false; } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } #endregion #region 刪除文件 /// <summary> /// 從FTP服務器上面刪除一個文件 /// </summary> /// <param name="RemoteFileName">遠程文件名</param> public void DeleteFile(string RemoteFileName) { try { if (!IsValidFileChars(RemoteFileName)) { throw new Exception("文件名非法!"); } Response = Open(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.DeleteFile); } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } #endregion #region 重命名文件 /// <summary> /// 更改一個文件的名稱或一個目錄的名稱 /// </summary> /// <param name="RemoteFileName">原始文件或目錄名稱</param> /// <param name="NewFileName">新的文件或目錄的名稱</param> public bool ReName(string RemoteFileName, string NewFileName) { try { if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(NewFileName)) { throw new Exception("文件名非法!"); } if (RemoteFileName == NewFileName) { return true; } if (FileExist(RemoteFileName)) { Request = OpenRequest(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.Rename); Request.RenameTo = NewFileName; Response = (FtpWebResponse)Request.GetResponse(); } else { throw new Exception("文件在服務器上不存在!"); } return true; } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } #endregion #region 拷貝、移動文件 /// <summary> /// 把當前目錄下面的一個文件拷貝到服務器上面另外的目錄中,注意,拷貝文件之后,當前工作目錄還是文件原來所在的目錄 /// </summary> /// <param name="RemoteFile">當前目錄下的文件名</param> /// <param name="DirectoryName">新目錄名稱。 /// 說明:如果新目錄是當前目錄的子目錄,則直接指定子目錄。如: SubDirectory1/SubDirectory2 ; /// 如果新目錄不是當前目錄的子目錄,則必須從根目錄一級一級的指定。如: ./NewDirectory/SubDirectory1/SubDirectory2 /// </param> /// <returns></returns> public bool CopyFileToAnotherDirectory(string RemoteFile, string DirectoryName) { string CurrentWorkDir = this.DirectoryPath; try { byte[] bt = DownloadFile(RemoteFile); GotoDirectory(DirectoryName); bool Success = UploadFile(bt, RemoteFile, false); this.DirectoryPath = CurrentWorkDir; return Success; } catch (Exception ep) { this.DirectoryPath = CurrentWorkDir; ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 把當前目錄下面的一個文件移動到服務器上面另外的目錄中,注意,移動文件之后,當前工作目錄還是文件原來所在的目錄 /// </summary> /// <param name="RemoteFile">當前目錄下的文件名</param> /// <param name="DirectoryName">新目錄名稱。 /// 說明:如果新目錄是當前目錄的子目錄,則直接指定子目錄。如: SubDirectory1/SubDirectory2 ; /// 如果新目錄不是當前目錄的子目錄,則必須從根目錄一級一級的指定。如: ./NewDirectory/SubDirectory1/SubDirectory2 /// </param> /// <returns></returns> public bool MoveFileToAnotherDirectory(string RemoteFile, string DirectoryName) { string CurrentWorkDir = this.DirectoryPath; try { if (DirectoryName == "") return false; if (!DirectoryName.StartsWith("/")) DirectoryName = "/" + DirectoryName; if (!DirectoryName.EndsWith("/")) DirectoryName += "/"; bool Success = ReName(RemoteFile, DirectoryName + RemoteFile); this.DirectoryPath = CurrentWorkDir; return Success; } catch (Exception ep) { this.DirectoryPath = CurrentWorkDir; ErrorMsg = ep.ToString(); throw ep; } } #endregion #region 建立、刪除子目錄 /// <summary> /// 在FTP服務器上當前工作目錄建立一個子目錄 /// </summary> /// <param name="DirectoryName">子目錄名稱</param> public bool MakeDirectory(string DirectoryName) { try { if (!IsValidPathChars(DirectoryName)) { throw new Exception("目錄名非法!"); } if (DirectoryExist(DirectoryName)) { throw new Exception("服務器上面已經存在同名的文件名或目錄名!"); } Response = Open(new Uri(this.Uri.ToString() + DirectoryName), WebRequestMethods.Ftp.MakeDirectory); return true; } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 從當前工作目錄中刪除一個子目錄 /// </summary> /// <param name="DirectoryName">子目錄名稱</param> public bool RemoveDirectory(string DirectoryName) { try { if (!IsValidPathChars(DirectoryName)) { throw new Exception("目錄名非法!"); } if (!DirectoryExist(DirectoryName)) { throw new Exception("服務器上面不存在指定的文件名或目錄名!"); } Response = Open(new Uri(this.Uri.ToString() + DirectoryName), WebRequestMethods.Ftp.RemoveDirectory); return true; } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } #endregion #region 文件、目錄名稱有效性判斷 /// <summary> /// 判斷目錄名中字符是否合法 /// </summary> /// <param name="DirectoryName">目錄名稱</param> public bool IsValidPathChars(string DirectoryName) { char[] invalidPathChars = Path.GetInvalidPathChars(); char[] DirChar = DirectoryName.ToCharArray(); foreach (char C in DirChar) { if (Array.BinarySearch(invalidPathChars, C) >= 0) { return false; } } return true; } /// <summary> /// 判斷文件名中字符是否合法 /// </summary> /// <param name="FileName">文件名稱</param> public bool IsValidFileChars(string FileName) { char[] invalidFileChars = Path.GetInvalidFileNameChars(); char[] NameChar = FileName.ToCharArray(); foreach (char C in NameChar) { if (Array.BinarySearch(invalidFileChars, C) >= 0) { return false; } } return true; } #endregion #region 目錄切換操作 /// <summary> /// 進入一個目錄 /// </summary> /// <param name="DirectoryName"> /// 新目錄的名字。 /// 說明:如果新目錄是當前目錄的子目錄,則直接指定子目錄。如: SubDirectory1/SubDirectory2 ; /// 如果新目錄不是當前目錄的子目錄,則必須從根目錄一級一級的指定。如: ./NewDirectory/SubDirectory1/SubDirectory2 /// </param> public bool GotoDirectory(string DirectoryName) { string CurrentWorkPath = this.DirectoryPath; try { DirectoryName = DirectoryName.Replace("\\", "/"); string[] DirectoryNames = DirectoryName.Split(new char[] { '/' }); if (DirectoryNames[0] == ".") { this.DirectoryPath = "/"; if (DirectoryNames.Length == 1) { return true; } Array.Clear(DirectoryNames, 0, 1); } bool Success = false; foreach (string dir in DirectoryNames) { if (dir != null) { Success = EnterOneSubDirectory(dir); if (!Success) { this.DirectoryPath = CurrentWorkPath; return false; } } } return Success; } catch (Exception ep) { this.DirectoryPath = CurrentWorkPath; ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 從當前工作目錄進入一個子目錄 /// </summary> /// <param name="DirectoryName">子目錄名稱</param> private bool EnterOneSubDirectory(string DirectoryName) { try { if (DirectoryName.IndexOf("/") >= 0 || !IsValidPathChars(DirectoryName)) { throw new Exception("目錄名非法!"); } if (DirectoryName.Length > 0 && DirectoryExist(DirectoryName)) { if (!DirectoryName.EndsWith("/")) { DirectoryName += "/"; } _DirectoryPath += DirectoryName; return true; } else { return false; } } catch (Exception ep) { ErrorMsg = ep.ToString(); throw ep; } } /// <summary> /// 從當前工作目錄往上一級目錄 /// </summary> public bool ComeoutDirectory() { if (_DirectoryPath == "/") { ErrorMsg = "當前目錄已經是根目錄!"; throw new Exception("當前目錄已經是根目錄!"); } char[] sp = new char[1] { '/' }; string[] strDir = _DirectoryPath.Split(sp, StringSplitOptions.RemoveEmptyEntries); if (strDir.Length == 1) { _DirectoryPath = "/"; } else { _DirectoryPath = String.Join("/", strDir, 0, strDir.Length - 1); } return true; } #endregion #region 重載WebClient,支持FTP進度 internal class MyWebClient : WebClient { protected override WebRequest GetWebRequest(Uri address) { FtpWebRequest req = (FtpWebRequest)base.GetWebRequest(address); req.UsePassive = false; return req; } } #endregion } }
使用示例:
Uri ftpUrl = new Uri("ftp://192.168.1.100/"); FTPHelper ftp = new FTPHelper(ftpUrl, "用戶名", "密碼"); FileStruct[] files = ftp.ListFiles(); foreach (FileStruct fs in files) { if (fs.Name == filename) { MessageUtil.ShowTips("服務器中已經含有" + filename + "文件"); break; } } bool result = ftp.UploadFile(filePosition);