posts - 5,  comments - 5,  trackbacks - 0

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

          基本原理就是先建立Socket連接,然后發請求命令和取回應答碼。編碼方式采用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 內部變量
            /// <summary>
            /// 服務器返回的應答信息(包含應答碼)
            /// </summary>
            private string strMsg;
            /// <summary>
            /// 服務器返回的應答信息(包含應答碼)
            /// </summary>
            private string strReply;
            /// <summary>
            /// 服務器返回的應答碼
            /// </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>
            /// 接收和發送數據的緩沖區
            /// </summary>
            private static int BLOCK_SIZE = 512;
            Byte[] buffer = new Byte[ BLOCK_SIZE];
            /// <summary>
            /// 編碼方式
            /// </summary>
            Encoding ASCII = Encoding.Default;
            #endregion

            #region 內部函數

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

            /// <summary>
            /// 構造函數
            /// </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服務器IP地址
            /// </summary>
           
            public string RemoteHost
            {
             get
             {
              return strRemoteHost;
             }
             set
             {
              strRemoteHost = value;
             }
            }
            /// <summary>
            /// FTP服務器端口
            /// </summary>
            public int RemotePort
            {
             get
             {
              return strRemotePort;
             }
             set
             {
              strRemotePort = value;
             }
            }
            /// <summary>
            /// 當前服務器目錄
            /// </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");
             }

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

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

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


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

            #endregion

            #region 傳輸模式

            /// <summary>
            /// 設置傳輸模式
            /// </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();
             }

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

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

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

             //獲得結果
             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();//數據socket關閉時也會有返回碼
             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">本地目錄(不得以\結束)</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">本地目錄(不得以\結束)</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">本地目錄(不得以\結束)</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>
            /// 創建目錄
            /// </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>
            /// 將一行應答字符串記錄在strReply和strMsg
            /// 應答碼記錄在iReplyCode
            /// </summary>
            private void ReadReply()
            {
             strMsg = "";
             strReply = ReadLine();
             iReplyCode = Int32.Parse(strReply.Substring(0,3));
            }

            /// <summary>
            /// 建立進行數據連接的socket
            /// </summary>
            /// <returns>數據連接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>
            /// 關閉socket連接(用于登錄以前)
            /// </summary>
            private void CloseSocketConnect()
            {
             if(socketControl!=null)
             {
              socketControl.Close();
              socketControl = null;
             }
             bConnected = false;
            }

            /// <summary>
            /// 讀取Socket返回的所有字符串
            /// </summary>
            /// <returns>包含應答碼的字符串行</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后面雖沒有字符串,
              //但也會分配為空字符串給后面(也是最后一個)字符串數組,
              //所以最后一個mess是沒用的空字符串
              //但為什么不直接取mess[0],因為只有最后一行字符串應答碼與信息之間有空格
             }
             else
             {
              strMsg = mess[0];
             }
             if(!strMsg.Substring(3,1).Equals(" "))//返回字符串正確的是以應答碼(如220開頭,后面接一空格,再接問候字符串)
             {
              return ReadLine();
             }
             return strMsg;
            }


            /// <summary>
            /// 發送命令并獲取應答碼和最后一行應答字符串
            /// </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

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 随州市| 平定县| 舟曲县| 安陆市| 大丰市| 嫩江县| 察雅县| 鄄城县| 兴海县| 句容市| 易门县| 家居| 黄山市| 永福县| 中宁县| 保德县| 金寨县| 郯城县| 荆门市| 辽宁省| 泰宁县| 平遥县| 繁峙县| 武功县| 富平县| 湘潭市| 海城市| 天柱县| 诸城市| 徐水县| 田阳县| 沈阳市| 柳州市| 榆树市| 汉源县| 玉门市| 闵行区| 怀化市| 皋兰县| 塘沽区| 太湖县|