namespace HOTERP.Common { 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; 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);