posts - 5,  comments - 5,  trackbacks - 0

          .NET下的FTP上傳、下載文件操作類

          基本原理就是先建立Socket連接,然后發(fā)請求命令和取回應(yīng)答碼。編碼方式采用Encoding ASCII = Encoding.Default;來支持中文文件名。

          using System;
          using System.Net;
          using System.Net.Sockets;
          using System.Text;
          using System.IO;

          namespace PMTSS.Common
          {
           /// <summary>
           /// FTP 操作類
           /// </summary>
           public class FTP
           {
            private string strRemoteHost;
            private int strRemotePort;
            private string strRemotePath;
            private string strRemoteUser;
            private string strRemotePass;
            private Boolean bConnected;

            #region 內(nèi)部變量
            /// <summary>
            /// 服務(wù)器返回的應(yīng)答信息(包含應(yīng)答碼)
            /// </summary>
            private string strMsg;
            /// <summary>
            /// 服務(wù)器返回的應(yīng)答信息(包含應(yīng)答碼)
            /// </summary>
            private string strReply;
            /// <summary>
            /// 服務(wù)器返回的應(yīng)答碼
            /// </summary>
            private int iReplyCode;
            /// <summary>
            /// 進行控制連接的socket
            /// </summary>
            private Socket socketControl;
            /// <summary>
            /// 傳輸模式
            /// </summary>
            private TransferType trType;
            /// <summary>
            /// 傳輸模式:二進制類型、ASCII類型
            /// </summary>
            public enum TransferType
            {
             /// <summary>
             /// Binary
             /// </summary>
             Binary,
             /// <summary>
             /// ASCII
             /// </summary>
             ASCII
            };

            /// <summary>
            /// 接收和發(fā)送數(shù)據(jù)的緩沖區(qū)
            /// </summary>
            private static int BLOCK_SIZE = 512;
            Byte[] buffer = new Byte[ BLOCK_SIZE];
            /// <summary>
            /// 編碼方式
            /// </summary>
            Encoding ASCII = Encoding.Default;
            #endregion

            #region 內(nèi)部函數(shù)

            #region 構(gòu)造函數(shù)
            /// <summary>
            /// 缺省構(gòu)造函數(shù)
            /// </summary>
            public FTP()
            {
             strRemoteHost  = "";
             strRemotePath  = "";
             strRemoteUser  = "";
             strRemotePass  = "";
             strRemotePort  = 21;
             bConnected     = false;
            }

            /// <summary>
            /// 構(gòu)造函數(shù)
            /// </summary>
            /// <param name="remoteHost"></param>
            /// <param name="remotePath"></param>
            /// <param name="remoteUser"></param>
            /// <param name="remotePass"></param>
            /// <param name="remotePort"></param>
            public FTP( string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort )
            {
             strRemoteHost  = remoteHost;
             strRemotePath  = remotePath;
             strRemoteUser  = remoteUser;
             strRemotePass  = remotePass;
             strRemotePort  = remotePort;
             Connect();
            }
            public FTP( string remoteHost, string remotePath, string remoteUser, string remotePass)
            {
             strRemoteHost  = remoteHost;
             strRemotePath  = remotePath;
             strRemoteUser  = remoteUser;
             strRemotePass  = remotePass;
             strRemotePort  = 21;
             Connect();
            }
            #endregion

            #region 登陸
            /// <summary>
            /// FTP服務(wù)器IP地址
            /// </summary>
           
            public string RemoteHost
            {
             get
             {
              return strRemoteHost;
             }
             set
             {
              strRemoteHost = value;
             }
            }
            /// <summary>
            /// FTP服務(wù)器端口
            /// </summary>
            public int RemotePort
            {
             get
             {
              return strRemotePort;
             }
             set
             {
              strRemotePort = value;
             }
            }
            /// <summary>
            /// 當前服務(wù)器目錄
            /// </summary>
            public string RemotePath
            {
             get
             {
              return strRemotePath;
             }
             set
             {
              strRemotePath = value;
             }
            }
            /// <summary>
            /// 登錄用戶賬號
            /// </summary>
            public string RemoteUser
            {
             set
             {
              strRemoteUser = value;
             }
            }
            /// <summary>
            /// 用戶登錄密碼
            /// </summary>
            public string RemotePass
            {
             set
             {
              strRemotePass = value;
             }
            }

            /// <summary>
            /// 是否登錄
            /// </summary>
            public bool Connected
            {
             get
             {
              return bConnected;
             }
            }
            #endregion

            #region 鏈接
            /// <summary>
            /// 建立連接
            /// </summary>
            public void Connect()
            {
             socketControl = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
             IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), strRemotePort);
             // 鏈接
             try
             {
              socketControl.Connect(ep);
             }
             catch(Exception)
             {
              throw new IOException("Couldn't connect to remote server");
             }

             // 獲取應(yīng)答碼
             ReadReply();
             if(iReplyCode != 220)
             {
              DisConnect();
              throw new IOException(strReply.Substring(4));
             }

             // 登陸
             SendCommand("USER "+strRemoteUser);
             if( !(iReplyCode == 331 || iReplyCode == 230) )
             {
              CloseSocketConnect();//關(guān)閉連接
              throw new IOException(strReply.Substring(4));
             }
             if( iReplyCode != 230 )
             {
              SendCommand("PASS "+strRemotePass);
              if( !(iReplyCode == 230 || iReplyCode == 202) )
              {
               CloseSocketConnect();//關(guān)閉連接
               throw new IOException(strReply.Substring(4));
              }
             }
             bConnected = true;

             // 切換到目錄
             ChDir(strRemotePath);
            }


            /// <summary>
            /// 關(guān)閉連接
            /// </summary>
            public void DisConnect()
            {
             if( socketControl != null )
             {
              SendCommand("QUIT");
             }
             CloseSocketConnect();
            }

            #endregion

            #region 傳輸模式

            /// <summary>
            /// 設(shè)置傳輸模式
            /// </summary>
            /// <param name="ttType">傳輸模式</param>
            public void SetTransferType(TransferType ttType)
            {
             if(ttType == TransferType.Binary)
             {
              SendCommand("TYPE I");//binary類型傳輸
             }
             else
             {
              SendCommand("TYPE A");//ASCII類型傳輸
             }
             if (iReplyCode != 200)
             {
              throw new IOException(strReply.Substring(4));
             }
             else
             {
              trType = ttType;
             }
            }


            /// <summary>
            /// 獲得傳輸模式
            /// </summary>
            /// <returns>傳輸模式</returns>
            public TransferType GetTransferType()
            {
             return trType;
            }

            #endregion

            #region 文件操作
            /// <summary>
            /// 獲得文件列表
            /// </summary>
            /// <param name="strMask">文件名的匹配字符串</param>
            /// <returns></returns>
            public string[] Dir(string strMask)
            {
             // 建立鏈接
             if(!bConnected)
             {
              Connect();
             }

             //建立進行數(shù)據(jù)連接的socket
             Socket socketData = CreateDataSocket();

             //傳送命令
             SendCommand("NLST " + strMask);

             //分析應(yīng)答代碼
             if(!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226))
             {
              throw new IOException(strReply.Substring(4));
             }

             //獲得結(jié)果
             strMsg = "";
             while(true)
             {
              int iBytes = socketData.Receive(buffer, buffer.Length, 0);
              strMsg += ASCII.GetString(buffer, 0, iBytes);
              if(iBytes < buffer.Length)
              {
               break;
              }
             }
             char[] seperator = {'\n'};
             string[] strsFileList = strMsg.Split(seperator);
             socketData.Close();//數(shù)據(jù)socket關(guān)閉時也會有返回碼
             if(iReplyCode != 226)
             {
              ReadReply();
              if(iReplyCode != 226)
              {
               throw new IOException(strReply.Substring(4));
              }
             }
             return strsFileList;
            }


            /// <summary>
            /// 獲取文件大小
            /// </summary>
            /// <param name="strFileName">文件名</param>
            /// <returns>文件大小</returns>
            private long GetFileSize(string strFileName)
            {
             if(!bConnected)
             {
              Connect();
             }
             SendCommand("SIZE " + Path.GetFileName(strFileName));
             long lSize=0;
             if(iReplyCode == 213)
             {
              lSize = Int64.Parse(strReply.Substring(4));
             }
             else
             {
              throw new IOException(strReply.Substring(4));
             }
             return lSize;
            }


            /// <summary>
            /// 刪除
            /// </summary>
            /// <param name="strFileName">待刪除文件名</param>
            public void Delete(string strFileName)
            {
             if(!bConnected)
             {
              Connect();
             }
             SendCommand("DELE "+strFileName);
             if(iReplyCode != 250)
             {
              throw new IOException(strReply.Substring(4));
             }
            }


            /// <summary>
            /// 重命名(如果新文件名與已有文件重名,將覆蓋已有文件)
            /// </summary>
            /// <param name="strOldFileName">舊文件名</param>
            /// <param name="strNewFileName">新文件名</param>
            public void Rename(string strOldFileName,string strNewFileName)
            {
             if(!bConnected)
             {
              Connect();
             }
             SendCommand("RNFR "+strOldFileName);
             if(iReplyCode != 350)
             {
              throw new IOException(strReply.Substring(4));
             }
             //  如果新文件名與原有文件重名,將覆蓋原有文件
             SendCommand("RNTO "+strNewFileName);
             if(iReplyCode != 250)
             {
              throw new IOException(strReply.Substring(4));
             }
            }
            #endregion

            #region 上傳和下載
            /// <summary>
            /// 下載一批文件
            /// </summary>
            /// <param name="strFileNameMask">文件名的匹配字符串</param>
            /// <param name="strFolder">本地目錄(不得以\結(jié)束)</param>
            public void Get(string strFileNameMask,string strFolder)
            {
             if(!bConnected)
             {
              Connect();
             }
             string[] strFiles = Dir(strFileNameMask);
             foreach(string strFile in strFiles)
             {
              if(!strFile.Equals(""))//一般來說strFiles的最后一個元素可能是空字符串
              {
               Get(strFile,strFolder,strFile);
              }
             }
            }


            /// <summary>
            /// 下載一個文件
            /// </summary>
            /// <param name="strRemoteFileName">要下載的文件名</param>
            /// <param name="strFolder">本地目錄(不得以\結(jié)束)</param>
            /// <param name="strLocalFileName">保存在本地時的文件名</param>
            public void Get(string strRemoteFileName,string strFolder,string strLocalFileName)
            {
             if(!bConnected)
             {
              Connect();
             }
             SetTransferType(TransferType.Binary);
             if (strLocalFileName.Equals(""))
             {
              strLocalFileName = strRemoteFileName;
             }
             if(!File.Exists(strLocalFileName))
             {
              Stream st = File.Create(strLocalFileName);
              st.Close();
             }
             FileStream output = new
              FileStream(strFolder + "\\" + strLocalFileName,FileMode.Create);
             Socket socketData = CreateDataSocket();
             SendCommand("RETR " + strRemoteFileName);
             if(!(iReplyCode == 150 || iReplyCode == 125
              || iReplyCode == 226 || iReplyCode == 250))
             {
              throw new IOException(strReply.Substring(4));
             }
             while(true)
             {
              int iBytes = socketData.Receive(buffer, buffer.Length, 0);
              output.Write(buffer,0,iBytes);
              if(iBytes <= 0)
              {
               break;
              }
             }
             output.Close();
             if (socketData.Connected)
             {
              socketData.Close();
             }
             if(!(iReplyCode == 226 || iReplyCode == 250))
             {
              ReadReply();
              if(!(iReplyCode == 226 || iReplyCode == 250))
              {
               throw new IOException(strReply.Substring(4));
              }
             }
            }


            /// <summary>
            /// 上傳一批文件
            /// </summary>
            /// <param name="strFolder">本地目錄(不得以\結(jié)束)</param>
            /// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param>
            public void Put(string strFolder,string strFileNameMask)
            {
             string[] strFiles = Directory.GetFiles(strFolder,strFileNameMask);
             foreach(string strFile in strFiles)
             {
              //strFile是完整的文件名(包含路徑)
              Put(strFile);
             }
            }


            /// <summary>
            /// 上傳一個文件
            /// </summary>
            /// <param name="strFileName">本地文件名</param>
            public void Put(string strFileName)
            {
             if(!bConnected)
             {
              Connect();
             }
             Socket socketData = CreateDataSocket();
             SendCommand("STOR "+Path.GetFileName(strFileName));
             if( !(iReplyCode == 125 || iReplyCode == 150) )
             {
              throw new IOException(strReply.Substring(4));
             }
             FileStream input = new
              FileStream(strFileName,FileMode.Open);
             int iBytes = 0;
             while ((iBytes = input.Read(buffer,0,buffer.Length)) > 0)
             {
              socketData.Send(buffer, iBytes, 0);
             }
             input.Close();
             if (socketData.Connected)
             {
              socketData.Close();
             }
             if(!(iReplyCode == 226 || iReplyCode == 250))
             {
              ReadReply();
              if(!(iReplyCode == 226 || iReplyCode == 250))
              {
               throw new IOException(strReply.Substring(4));
              }
             }
            }

            #endregion

            #region 目錄操作
            /// <summary>
            /// 創(chuàng)建目錄
            /// </summary>
            /// <param name="strDirName">目錄名</param>
            public void MkDir(string strDirName)
            {
             if(!bConnected)
             {
              Connect();
             }
             SendCommand("MKD "+strDirName);
             if(iReplyCode != 257)
             {
              throw new IOException(strReply.Substring(4));
             }
            }


            /// <summary>
            /// 刪除目錄
            /// </summary>
            /// <param name="strDirName">目錄名</param>
            public void RmDir(string strDirName)
            {
             if(!bConnected)
             {
              Connect();
             }
             SendCommand("RMD "+strDirName);
             if(iReplyCode != 250)
             {
              throw new IOException(strReply.Substring(4));
             }
            }


            /// <summary>
            /// 改變目錄
            /// </summary>
            /// <param name="strDirName">新的工作目錄名</param>
            public void ChDir(string strDirName)
            {
             if(strDirName.Equals(".") || strDirName.Equals(""))
             {
              return;
             }
             if(!bConnected)
             {
              Connect();
             }
             SendCommand("CWD "+strDirName);
             if(iReplyCode != 250)
             {
              throw new IOException(strReply.Substring(4));
             }
             this.strRemotePath = strDirName;
            }

            #endregion

            /// <summary>
            /// 將一行應(yīng)答字符串記錄在strReply和strMsg
            /// 應(yīng)答碼記錄在iReplyCode
            /// </summary>
            private void ReadReply()
            {
             strMsg = "";
             strReply = ReadLine();
             iReplyCode = Int32.Parse(strReply.Substring(0,3));
            }

            /// <summary>
            /// 建立進行數(shù)據(jù)連接的socket
            /// </summary>
            /// <returns>數(shù)據(jù)連接socket</returns>
            private Socket CreateDataSocket()
            {
             SendCommand("PASV");
             if(iReplyCode != 227)
             {
              throw new IOException(strReply.Substring(4));
             }
             int index1 = strReply.IndexOf('(');
             int index2 = strReply.IndexOf(')');
             string ipData =
              strReply.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 strReply: " +
                strReply);
              }
              if (ch == ',' || i+1 == len)
              {
               try
               {
                parts[partCount++] = Int32.Parse(buf);
                buf="";
               }
               catch (Exception)
               {
                throw new IOException("Malformed PASV strReply: " +
                 strReply);
               }
              }
             }
             string ipAddress = parts[0] + "."+ parts[1]+ "." +
              parts[2] + "." + parts[3];
             int port = (parts[4] << 8) + parts[5];
             Socket s = new
              Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
             IPEndPoint ep = new
              IPEndPoint(IPAddress.Parse(ipAddress), port);
             try
             {
              s.Connect(ep);
             }
             catch(Exception)
             {
              throw new IOException("Can't connect to remote server");
             }
             return s;
            }


            /// <summary>
            /// 關(guān)閉socket連接(用于登錄以前)
            /// </summary>
            private void CloseSocketConnect()
            {
             if(socketControl!=null)
             {
              socketControl.Close();
              socketControl = null;
             }
             bConnected = false;
            }

            /// <summary>
            /// 讀取Socket返回的所有字符串
            /// </summary>
            /// <returns>包含應(yīng)答碼的字符串行</returns>
            private string ReadLine()
            {
             while(true)
             {
              int iBytes = socketControl.Receive(buffer, buffer.Length, 0);
              strMsg += ASCII.GetString(buffer, 0, iBytes);
              if(iBytes < buffer.Length)
              {
               break;
              }
             }
             char[] seperator = {'\n'};
             string[] mess = strMsg.Split(seperator);
             if(strMsg.Length > 2)
             {
              strMsg = mess[mess.Length-2];
              //seperator[0]是10,換行符是由13和0組成的,分隔后10后面雖沒有字符串,
              //但也會分配為空字符串給后面(也是最后一個)字符串數(shù)組,
              //所以最后一個mess是沒用的空字符串
              //但為什么不直接取mess[0],因為只有最后一行字符串應(yīng)答碼與信息之間有空格
             }
             else
             {
              strMsg = mess[0];
             }
             if(!strMsg.Substring(3,1).Equals(" "))//返回字符串正確的是以應(yīng)答碼(如220開頭,后面接一空格,再接問候字符串)
             {
              return ReadLine();
             }
             return strMsg;
            }


            /// <summary>
            /// 發(fā)送命令并獲取應(yīng)答碼和最后一行應(yīng)答字符串
            /// </summary>
            /// <param name="strCommand">命令</param>
            private void SendCommand(string strCommand)
            {
             Byte[] cmdBytes = ASCII.GetBytes((strCommand + "\r\n").ToCharArray());
             socketControl.Send(cmdBytes, cmdBytes.Length, 0);
             ReadReply();
            }

            #endregion
           }
          }

          posted on 2007-09-03 01:34 曾科 閱讀(329) 評論(0)  編輯  收藏 所屬分類: C#
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(3)

          隨筆檔案

          文章分類

          文章檔案

          相冊

          .net

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 三江| 瑞丽市| 招远市| 阿克苏市| 临泽县| 渭源县| 新丰县| 大港区| 铁力市| 保定市| 石城县| 文水县| 济宁市| 吴堡县| 高尔夫| 鄂尔多斯市| 东乌| 茂名市| 丽江市| 泽普县| 延川县| 梓潼县| 河南省| 青神县| 汤阴县| 锡林浩特市| 含山县| 山阴县| 黄大仙区| 米泉市| 水城县| 肥西县| 奎屯市| 舞阳县| 平利县| 博客| 达孜县| 平定县| 宜昌市| 昭平县| 平泉县|