天天看點

C# FTP簡單幫助類

最近做的項目需要用到FTP傳輸檔案,是以寫這麼一個幫助類,功能比較簡單,可以實作基本的上傳和下載下傳,包括遞歸下載下傳檔案夾,代碼如下:

public class FtpAccess : IDisposable
    {
        #region 私有變量
        /// <summary>
        /// Ftp請求對象
        /// </summary>
        private FtpWebRequest _request = null;


        /// <summary>
        /// Ftp響應對象
        /// </summary>
        private FtpWebResponse _response = null;


        /// <summary>
        /// 是否需要删除臨時檔案
        /// </summary>
        private bool _isDeleteTempFile = false;


        /// <summary>
        /// 異步上傳時臨時生成的檔案
        /// </summary>
        private string _uploadTempFile = "";


        #endregion


        #region 公共屬性


        ///<summary>
        /// Ftp伺服器位址:wifi.ttoocc.com/
        /// </summary>
        public string ServerUri { get; set; }


        /// <summary>
        /// Ftp伺服器登入使用者
        /// </summary>
        public string UserName { get; set; }


        /// <summary>
        /// Ftp伺服器登入密碼
        /// </summary>
        public string Password { get; set; }


        #endregion


        #region 構造函數
        public FtpAccess() { }
        /// <summary>
        /// 執行個體化FTP幫助類
        /// </summary>
        /// <param name="serverUri">FTP伺服器位址(IP或域名)</param>
        /// <param name="userName">FTP使用者名</param>
        /// <param name="password">FTP密碼</param>
        public FtpAccess(string serverUri, string userName, string password)
        {
            ServerUri = serverUri;
            UserName = userName;
            Password = password;
        }
        #endregion


        #region 實作接口
        public void Dispose()
        {
            if (_request != null)
            {
                _request.Abort();
                _request = null;
            }
            if (_response != null)
            {
                _response.Close();
                _response = null;
            }
        }
        #endregion


        #region 事件
        /// <summary>
        /// 上傳檔案
        /// </summary>
        /// <param name="fileLocalPath">需要上傳的檔案</param>
        /// <param name="remoteDir">目标路徑</param>
        /// <param name="newFileName">新的檔案名</param>
        public bool UploadFile(string fileLocalPath, string remoteDir, string newFileName)
        {
            FileInfo file = new FileInfo(fileLocalPath);
            if (remoteDir.Trim() == "")
            {
                return false;
            }
            string URI = "FTP://" + ServerUri + "/" + remoteDir + "/" + newFileName;
            _request = null;
            if (!FtpIsExistsDir(remoteDir))
            {
                CreateDir(remoteDir);
            }
            if (FtpIsExistsFile(remoteDir + "/" + newFileName))
            {
                _request = GetRequest(URI);
                _request.KeepAlive = false;
                _request.Method = System.Net.WebRequestMethods.Ftp.DeleteFile; //删除
                _request.GetResponse();
            }
            //URI = "FTP://" + hostname + "/" + targetDir + "/" + newFileName;
            _request = null;
            _request = GetRequest(URI);
            _request.UseBinary = true;
            _request.UsePassive = true;
            _request.KeepAlive = false;
            _request.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
            //指定檔案傳輸的資料類型


            //告訴ftp檔案大小
            _request.ContentLength = file.Length;
            //緩沖大小設定為2KB
            int BufferSize = 2048, lastBufferSize, count;
            //計算包個數
            count = (int)file.Length / BufferSize + 1;
            //計算最後一個包大小
            lastBufferSize = (int)file.Length % BufferSize;
            byte[] content = new byte[BufferSize];
            int dataRead;
            //打開一個檔案流 (System.IO.FileStream) 去讀上傳的檔案
            using (FileStream fs = file.OpenRead())
            {
                try
                {
                    //把上傳的檔案寫入流
                    using (Stream rs = _request.GetRequestStream())
                    {
                        while (count > 1)
                        {
                            dataRead = fs.Read(content, 0, BufferSize);
                            rs.Write(content, 0, BufferSize);
                            count--;
                        }
                        content = new byte[lastBufferSize];
                        dataRead = fs.Read(content, 0, lastBufferSize);
                        rs.Write(content, 0, lastBufferSize);
                        rs.Close();
                        rs.Dispose();
                        fs.Close();
                        fs.Dispose();
                        return true;
                    }
                }
                catch (Exception)
                {
                    return false;
                }
                finally
                {
                    fs.Close();
                    fs.Dispose();
                }
            }


        }




        /// <summary>
        /// 下載下傳檔案
        /// </summary>
        /// <param name="localDir">下載下傳至本地路徑</param>
        /// <param name="ftpDir">ftp目标檔案路徑</param>
        /// <param name="ftpFile">從ftp要下載下傳的檔案名</param>
        public void DownloadFile(string localDir, string ftpDir, string ftpFile)
        {
            string URI = "FTP://" + ServerUri + "/" + ftpDir + "/" + ftpFile;
            string tmpname = Guid.NewGuid().ToString();
            string localfile = localDir + @"\" + tmpname;
            if (!Directory.Exists(localDir))
                Directory.CreateDirectory(localDir);
            _request = GetRequest(URI);
            _request.Method = System.Net.WebRequestMethods.Ftp.DownloadFile;
            _request.UseBinary = true;
            _request.UsePassive = false;
            using (FtpWebResponse response = (FtpWebResponse)_request.GetResponse())
            {
                using (Stream responseStream = response.GetResponseStream())
                {
                    using (FileStream fs = new FileStream(localfile, FileMode.CreateNew))
                    {
                        try
                        {
                            byte[] buffer = new byte[2048];
                            int read = 0;
                            do
                            {
                                read = responseStream.Read(buffer, 0, buffer.Length);
                                fs.Write(buffer, 0, read);
                            } while (read != 0);
                            responseStream.Close();
                            fs.Flush();
                            fs.Close();
                        }
                        catch (Exception)
                        {
                            fs.Close();
                            File.Delete(localfile);
                            throw;
                        }
                    }
                    responseStream.Close();
                }
                response.Close();
            }


            try
            {
                File.Delete(localDir + @"\" + ftpFile);
                File.Move(localfile, localDir + @"\" + ftpFile);
            }
            catch (Exception ex)
            {
                File.Delete(localfile);
                throw ex;
            }
            _request = null;
        }
        /// <summary>
        /// 從FTP上下載下傳檔案夾及其内容(遞歸)
        /// </summary>
        /// <param name="localDir"></param>
        /// <param name="ftpDir"></param>
        /// <returns></returns>
        public bool DownloadDirectory(string localDir, string ftpDir)
        {
            var list = GetDirectoriesListInfo(ftpDir);
            foreach (var item in list)
            {
                if (item.Groups[1].Value == "d")
                {
                    DownloadDirectory(localDir + @"\" + item.Groups[6].Value, ftpDir + "/" + item.Groups[6].Value);
                }
                else
                {
                    var file = new FileInfo(localDir + @"\" + item.Groups[6].Value);
                    if (file.Exists)
                    {
                        var ftpDateTime = GetLastModified(ftpDir + @"\" + item.Groups[6].Value);
                        var localDataTime = file.LastWriteTime;
                        if (ftpDateTime <= localDataTime)//若本地檔案比FTP檔案新,則不用下載下傳該檔案
                            continue;
                    }
                    DownloadFile(localDir, ftpDir, item.Groups[6].Value);
                }
            }
            return true;
        }
        /// <summary>
        /// 搜尋遠端檔案
        /// </summary>
        /// <param name="targetDir">遠端檔案夾(不能以"/"結尾) e.q. "aaa/bbb/ccc"</param>
        /// <returns></returns>
        public List<string> GetDirectoriesList(string targetDir)
        {
            var lastDirName = targetDir.Substring(targetDir.LastIndexOf('/') + 1);
            List<string> result = new List<string>();
            try
            {
                string URI = "FTP://" + ServerUri + "/" + targetDir;
                _request = GetRequest(URI);
                _request.Method = System.Net.WebRequestMethods.Ftp.ListDirectory;
                _request.UsePassive = true;
                _request.UseBinary = true;


                string str = GetStringResponse(_request);
                str = str.Replace(lastDirName + "/", null);
                if (str != string.Empty)
                    result.AddRange(str.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries));
                return result;
            }
            catch { return null; }
        }
        public List<string> GetDirectoriesList(string targetDir, string searchKey)
        {
            var lastDirName = targetDir.Substring(targetDir.LastIndexOf('/') + 1);
            List<string> result = new List<string>();
            try
            {
                string URI = "FTP://" + ServerUri + "/" + targetDir;
                _request = GetRequest(URI);
                _request.Method = System.Net.WebRequestMethods.Ftp.ListDirectory;
                _request.UsePassive = true;
                _request.UseBinary = true;


                string str = GetStringResponse(_request);
                str = str.Replace(lastDirName + "/", null);
                if (str != string.Empty)
                    result.AddRange(str.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries));
                return result.Where(m => m.Contains(searchKey)).ToList();
            }
            catch { return null; }
        }
        /// <summary>
        /// 擷取FTP指定目錄下檔案及檔案夾清單
        /// </summary>
        /// <param name="targetDir"></param>
        /// <returns></returns>
        public List<Match> GetDirectoriesListInfo(string targetDir)
        {
            var lastDirName = targetDir.Substring(targetDir.LastIndexOf('/') + 1);
            List<Match> result = new List<Match>();
            try
            {
                string URI = "FTP://" + ServerUri + "/" + targetDir;
                _request = GetRequest(URI);
                _request.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails;
                _request.UsePassive = true;
                _request.UseBinary = true;


                string str = GetStringResponse(_request);
                List<string> strs = new List<string>();
                if (str != string.Empty)
                    strs.AddRange(str.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries));
                Regex regex = new Regex(@"^([d-])([rwxt-]{3}){3}\s+\d{1,}\s+.*?(\d{1,})\s+(\w+\s+\d{1,2}\s+(?:\d{4})?)(\d{1,2}:\d{2})?\s+(.+?)\s?$", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
                foreach (var item in strs)
                {
                    Match match = regex.Match(item);
                    result.Add(match);
                }
                return result;
            }
            catch { return null; }
        }


        /// <summary>
        /// 擷取檔案或檔案夾的最後修改時間
        /// </summary>
        /// <param name="path">路徑</param>
        /// <returns></returns>
        private DateTime GetLastModified(string path)
        {
            try
            {
                string uri = "ftp://" + ServerUri + "/" + path;
                _request = GetRequest(uri);
                _request.Method = WebRequestMethods.Ftp.GetDateTimestamp;
                _response = (FtpWebResponse)_request.GetResponse();
                return _response.LastModified;
            }
            catch (Exception)
            {
                return DateTime.MinValue;
            }
        }


        /// <summary>
        /// 在ftp伺服器上建立目錄
        /// </summary>
        /// <param name="dirName">目錄名稱</param>
        /// <returns></returns>
        public bool CreateDir(string dirName)
        {
            try
            {
                string uri = "ftp://" + ServerUri + "/" + dirName;
                _request = GetRequest(uri);
                _request.Method = WebRequestMethods.Ftp.MakeDirectory;
                _response = (FtpWebResponse)_request.GetResponse();
                _response.Close();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }


        /// <summary>
        /// 删除目錄
        /// </summary>
        /// <param name="dirName">删除的目錄名稱</param>
        public bool DelDir(string dirName)
        {
            try
            {
                string uri = "ftp://" + ServerUri + "/" + dirName;
                _request = GetRequest(uri);
                _request.Method = WebRequestMethods.Ftp.RemoveDirectory;
                _response = (FtpWebResponse)_request.GetResponse();
                _response.Close();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }


        /// <summary>
        /// 檔案重命名
        /// </summary>
        /// <param name="currentFilename">目前目錄名稱</param>
        /// <param name="newFilename">重命名目錄名稱</param>
        public bool Rename(string currentFilename, string newFilename)
        {
            try
            {
                FileInfo fileInf = new FileInfo(currentFilename);
                string uri = "ftp://" + ServerUri + "/" + fileInf.Name;
                _request = GetRequest(uri);
                _request.Method = WebRequestMethods.Ftp.Rename;
                _request.RenameTo = newFilename;
                _response = (FtpWebResponse)_request.GetResponse();
                _response.Close();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }


        /// <summary>
        /// 判斷ftp伺服器上該目錄是否存在
        /// </summary>
        /// <param name="dirName"></param>
        /// <param name="ftpHostIP"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool FtpIsExistsDir(string dirName)
        {
            bool flag = true;
            try
            {
                string uri = "ftp://" + ServerUri + "/" + dirName;
                _request = GetRequest(uri);
                _request.Method = WebRequestMethods.Ftp.ListDirectory;
                _response = (FtpWebResponse)_request.GetResponse();
                _response.Close();
            }
            catch (Exception)
            {
                flag = false;
            }
            return flag;
        }


        /// <summary>
        /// 檢測檔案是否存在
        /// </summary>
        /// <param name="fileFullName"></param>
        /// <param name="ftpHostIP"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool FtpIsExistsFile(string fileFullName)
        {
            bool flag = true;
            try
            {
                string uri = "ftp://" + ServerUri + "/" + fileFullName;
                _request = GetRequest(uri);
                _request.Method = WebRequestMethods.Ftp.GetFileSize;
                _response = (FtpWebResponse)_request.GetResponse();
                _response.Close();
            }
            catch (Exception)
            {
                flag = false;
            }
            return flag;
        }
        private FtpWebRequest GetRequest(string URI)
        {
            //根據伺服器資訊FtpWebRequest建立類的對象
            FtpWebRequest result = (FtpWebRequest)FtpWebRequest.Create(URI);
            //提供身份驗證資訊
            result.Credentials = new System.Net.NetworkCredential(UserName, Password);
            //設定請求完成之後是否保持到FTP伺服器的控制連接配接,預設值為true
            result.KeepAlive = false;
            return result;
        }


        private string GetStringResponse(FtpWebRequest ftp)
        {
            //Get the result, streaming to a string
            string result = "";
            using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
            {
                long size = response.ContentLength;
                using (Stream datastream = response.GetResponseStream())
                {
                    using (StreamReader sr = new StreamReader(datastream, System.Text.Encoding.UTF8))
                    {
                        result = sr.ReadToEnd();
                        sr.Close();
                    }
                    datastream.Close();
                }
                response.Close();
            }
            return result;
        }
        #endregion
    }
           

繼續閱讀