所谓的潇洒

导航

FTP操作

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;

namespace Common
{
    /// <summary>
    /// FTP类
    /// </summary>
    public class FTP
    {
        private string _ftpServerIP;
        private string _ftpUserName;
        private string _ftpPassword;
        private Uri ftpUri;
        private string _path;

        /// <summary>
        ///
        /// </summary>
        /// <param name="ftpServerIp">ip:port,默认21端口可以只写ip</param>
        /// <param name="username"></param>
        /// <param name="passwd"></param>
        public FTP(string ftpServerIp, string username, string passwd)
        {
            _ftpServerIP = ftpServerIp;
            _ftpUserName = username;
            _ftpPassword = passwd;
            this.ftpUri = new Uri("ftp://" + ftpServerIp);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="ftpServerIp">ip:port,默认21端口可以只写ip</param>
        /// <param name="username"></param>
        /// <param name="passwd"></param>
        /// <param name="ftp_path"></param>
        public FTP(string ftpServerIp, string username, string passwd, string ftp_path) : this(ftpServerIp, username, passwd)
        {
            _path = ftp_path;
            this.ftpUri = new Uri("ftp://" + ftpServerIp + "/" + ftp_path);
        }

        /// <summary>
        /// 获取文件及文件夹列表
        /// </summary>
        /// <returns></returns>
        public List<FileStruct> GetList()
        {
            string dataString = GetFiles();
            DirectoryListParser parser = new DirectoryListParser(dataString);
            return parser.MyListArray;
        }

        /// <summary>
        /// 获得当前文件夹下的所有文件夹
        /// </summary>
        /// <returns></returns>
        public List<string> GetAllFolder()
        {
            string dataString = GetFiles();
            DirectoryListParser parser = new DirectoryListParser(dataString);
            List<string> result = new List<string>();
            parser.DirectoryList.ForEach(x => result.Add(x.Name));
            return result;
        }

        /// <summary>
        /// 获得当前文件夹下的所有文件
        /// </summary>
        /// <returns></returns>
        public List<string> GetAllFiles()
        {
            string dataString = GetFiles();
            DirectoryListParser parser = new DirectoryListParser(dataString);
            List<string> result = new List<string>();
            parser.FileList.ForEach(x => result.Add(x.Name));
            return result;
        }

        private string GetFiles()
        {
            WebRequest listRequest = WebRequest.Create(ftpUri);
            listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
            listRequest.Credentials = new NetworkCredential(_ftpUserName, _ftpPassword);

            WebResponse listResponse = listRequest.GetResponse();
            Stream responseStream = listResponse.GetResponseStream();
            StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8);

            string result = "";
            if (readStream != null) result = readStream.ReadToEnd();

            listResponse.Close();
            responseStream.Close();
            readStream.Close();
            return result;
        }

        /// <summary>
        /// 创建文件夹
        /// </summary>
        /// <param name="dirName">目录,如"aa/cc/bb",只创建bb文件夹</param>
        public bool MakeDir(string dirName)
        {
            bool success = TryMakeDir(dirName);
            if (!success)
            {
                success = TryMakeDir(dirName);
                if (!success) success = TryMakeDir(dirName, true);
            }
            return success;
        }

        private bool TryMakeDir(string dirName, bool writeLog = false)
        {
            try
            {
                var reqFTP = WebRequest.Create(new Uri(ftpUri + "/" + dirName));
                reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory;
                reqFTP.Credentials = new NetworkCredential(_ftpUserName, _ftpPassword);
                WebResponse response = reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();
                ftpStream.Close();
                response.Close();
                return true;
            }
            catch (Exception ex)
            {
                if (writeLog) LogHelper.logger.Error(ex);
                return false;
            }
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="localFile"></param>
        /// <param name="remoteFileName"></param>
        /// <returns></returns>
        public bool Upload(string localFileName, string remoteFileName)
        {
            bool success = TryUpload(localFileName, remoteFileName);
            if (!success)
            {
                success = TryUpload(localFileName, remoteFileName);
                if (!success) success = TryUpload(localFileName, remoteFileName, true);
            }
            return success;
        }

        private bool TryUpload(string localFileName, string remoteFileName, bool writeLog = false)
        {
            try
            {
                string uri = string.Empty;
                if (this.ftpUri.ToString().EndsWith("/")) uri = this.ftpUri + remoteFileName;
                else uri = this.ftpUri + "/" + remoteFileName;
                WebClient myWebClient = new WebClient();
                myWebClient.Credentials = new NetworkCredential(_ftpUserName, _ftpPassword);
                byte[] responseArray = myWebClient.UploadFile(uri, localFileName);
                return true;
            }
            catch (Exception ex)
            {
                if (writeLog) LogHelper.logger.Error($"Upload({localFileName},{remoteFileName})", ex);
                return false;
            }
        }

        /// <summary>
        /// 追加文件内容到远端文件,如果远端文件不存在则上传
        /// </summary>
        /// <param name="localFileName">本地文件,如"D:\\aa.txt"</param>
        /// <param name="remoteFileName">ftp文件,如"A/B/b.txt"</param>
        public void AppendFile(string localFileName, string remoteFileName)
        {
            try
            {
                if (!File.Exists(localFileName)) return;
                FileInfo fileInf = new FileInfo(localFileName);
                string uri = $"ftp://{_ftpServerIP}/{_path}/{remoteFileName}";
                var reqFTP = WebRequest.Create(new Uri(uri));
                reqFTP.Credentials = new NetworkCredential(_ftpUserName, _ftpPassword);
                reqFTP.Method = WebRequestMethods.Ftp.AppendFile;
                reqFTP.ContentLength = fileInf.Length;
                int buffLength = 2048;
                byte[] buff = new byte[buffLength];
                int contentLen;

                using (FileStream fs = fileInf.OpenRead())
                using (Stream strm = reqFTP.GetRequestStream())
                {
                    contentLen = fs.Read(buff, 0, buffLength);
                    while (contentLen != 0)
                    {
                        strm.Write(buff, 0, contentLen);
                        contentLen = fs.Read(buff, 0, buffLength);
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.logger.Error(ex);
            }
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="fileName">文件名,如“A/B/b.txt”</param>
        public bool Delete(string fileName)
        {
            try
            {
                string uri = $"ftp://{_ftpServerIP}/{_path}/{fileName}";
                var  reqFTP = WebRequest.Create(new Uri(uri));
                reqFTP.Credentials = new NetworkCredential(_ftpUserName, _ftpPassword);
                reqFTP.Method = WebRequestMethods.Ftp.DeleteFile;
                string result = String.Empty;
                using (var response = reqFTP.GetResponse())
                using (Stream datastream = response.GetResponseStream())
                using (StreamReader sr = new StreamReader(datastream))
                {
                    result = sr.ReadToEnd();
                }
                return true;
            }
            catch (Exception ex)
            {
                LogHelper.logger.Error(ex);
                return false;
            }
        }

        /// <summary>
        /// 重命名目录
        /// </summary>
        /// <param name="currentFilename">原来名称</param>
        /// <param name="newFilename">新名称</param>
        public bool ReName(string currentFilename, string newFilename)
        {
            FtpWebRequest reqFTP;
            try
            {
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpUri + currentFilename));
                reqFTP.Method = WebRequestMethods.Ftp.Rename;
                reqFTP.RenameTo = newFilename;
                reqFTP.UseBinary = true;
                reqFTP.Credentials = new NetworkCredential(_ftpUserName, _ftpPassword);
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();
                ftpStream.Close();
                response.Close();
                return true;
            }
            catch (Exception ex)
            {
                LogHelper.logger.Error(ex);
                return false;
            }
        }

        /// <summary>
        /// 判断目录是否存在
        /// </summary>
        /// <param name="path">文件夹所在目录,如:"aa/bb"</param>
        /// <param name="FolderName">文件夹名称,如:"cc"</param>
        /// <returns></returns>
        public bool DirectoryExist(string path, string FolderName)
        {
            try
            {
                string uri = $"ftp://{_ftpServerIP}/{_path}/{path}";
                WebRequest reqFTP = WebRequest.Create(new Uri(uri));
                reqFTP.Credentials = new NetworkCredential(this._ftpUserName, this._ftpPassword);
                reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;

                WebResponse response = reqFTP.GetResponse();
                string result = "";
                StreamReader readStream = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                if (readStream != null)
                {
                    result = readStream.ReadToEnd();
                }
                response.Close();

                LogHelper.logger.Debug($"DirectoryExist({path}, {FolderName}) return {result}");
                int index = result.IndexOf(FolderName + "\r\n");
                return (index == 0 || (index > 0 && result.Substring(index - 1, 1) == "\n"));
            }
            catch
            {
                return false;
            }
        }

        public bool DirectoryExist_ServerU(string path)
        {
            string uri = $"ftp://{_ftpServerIP}/{_path}/{path}";
            FtpWebRequest reqFtp = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
            reqFtp.UseBinary = true;
            reqFtp.Credentials = new NetworkCredential(_ftpUserName, _ftpPassword);
            reqFtp.Method = WebRequestMethods.Ftp.ListDirectory;
            FtpWebResponse resFtp = null;
            try
            {
                resFtp = (FtpWebResponse)reqFtp.GetResponse();
                FtpStatusCode code = resFtp.StatusCode;
                resFtp.Close();
                return true;
            }
            catch
            {
                if(resFtp != null) resFtp.Close();
                return false;
            }
        }

        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="folderName"></param>
        public bool RemoveDirectory(string folderName)
        {
            try
            {
                string uri = ftpUri + "/" + folderName;
                FtpWebRequest reqFTP;
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
                //reqFTP.EnableSsl = false;
                reqFTP.Credentials = new NetworkCredential(_ftpUserName, _ftpPassword);
                reqFTP.KeepAlive = false;
                reqFTP.Method = WebRequestMethods.Ftp.RemoveDirectory;

                string result = String.Empty;
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                long size = response.ContentLength;
                Stream datastream = response.GetResponseStream();
                StreamReader sr = new StreamReader(datastream);
                result = sr.ReadToEnd();
                sr.Close();
                datastream.Close();
                response.Close();
                return true;
            }
            catch (Exception ex)
            {
                LogHelper.logger.Error(ex);
                return false;
            }
        }

        public bool DownFile(string fileName, string localName)
        {
            try
            {
                string uri = string.Empty;
                if (this.ftpUri.ToString().EndsWith("/")) uri = this.ftpUri + fileName;
                else uri = this.ftpUri + "/" + fileName;
                WebClient myWebClient = new WebClient();
                myWebClient.Credentials = new NetworkCredential(_ftpUserName, _ftpPassword);
                myWebClient.DownloadFile(uri, localName);
                return File.Exists(localName);
            }
            catch (Exception ex)
            {
                LogHelper.logger.Error(fileName, ex);
                return false;
            }
        }
    }

    public struct FileStruct
    {
        /// <summary>
        /// 所有者
        /// </summary>
        public string Owner;
        /// <summary>
        /// 是否为目录
        /// </summary>
        public bool IsDirectory;
        /// <summary>
        /// 更新时间
        /// </summary>
        public string CreateTime;
        /// <summary>
        /// 名称
        /// </summary>
        public string Name;

        /// <summary>
        /// 文件大小
        /// </summary>
        public int FileSize;

        /// <summary>
        /// 类型
        /// </summary>
        public string FileType;
    }

    public class DirectoryListParser
    {
        private List<FileStruct> _myListArray;

        public DirectoryListParser(string responseString)
        {
            _myListArray = GetList(responseString);
        }

        public List<FileStruct> MyListArray { get { return _myListArray; } }

        /// <summary>
        /// 文件列表
        /// </summary>
        public List<FileStruct> FileList { get { return _myListArray.Where(x => !x.IsDirectory).ToList(); } }

        /// <summary>
        /// 目录列表
        /// </summary>
        public List<FileStruct> DirectoryList { get { return _myListArray.Where(x => x.IsDirectory).ToList(); } }

        private List<FileStruct> GetList(string datastring)
        {
            List<FileStruct> myListArray = new List<FileStruct>();
            string[] dataRecords = datastring.Split('\n');
            int style = GetFileListStyle(dataRecords);
            foreach (string s in dataRecords)
            {
                if (style > 0 && s != "")
                {
                    FileStruct f = new FileStruct();
                    f.Name = "..";
                    if (style == 1) f = ParseFileStructFromUnixStyleRecord(s);
                    else if (style == 2) f = ParseFileStructFromWindowsStyleRecord(s);
                    if (f.Name != "" && f.Name != "." && f.Name != "..") myListArray.Add(f);
                }
            }
            return myListArray;
        }

        /// <summary>
        /// 获取文件风格
        /// </summary>
        /// <param name="recordList"></param>
        /// <returns>0-未知,1-Unix风格,2-Windows风格</returns>
        public int GetFileListStyle(string[] recordList)
        {
            foreach (string s in recordList)
            {
                if (s.Length > 10 && Regex.IsMatch(s.Substring(0, 10), "(-|d)((-|r)(-|w)(-|x)){3}")) return 1;
                else if (s.Length > 8 && Regex.IsMatch(s.Substring(0, 8), "[0-9]{2}-[0-9]{2}-[0-9]{2}")) return 2;
            }
            return 0;
        }

        private FileStruct ParseFileStructFromWindowsStyleRecord(string Record)
        {
            // Assuming the record style as
            //文件夹 02-03-04  07:46PM       <DIR>          Append
            //文件 02-12-11  02:20AM                26599 xxd.asp
            FileStruct f = new FileStruct();
            string[] arr = Regex.Split(Record.Trim(), "\\s+");

            f.Name = arr[3];
            f.CreateTime = arr[0] + "  " + arr[1];

            if (arr[2] == "<DIR>")
            {
                f.FileSize = 0;
                f.IsDirectory = true;
                f.FileType = "文件夹";
            }
            else
            {
                f.FileSize = int.Parse(arr[2]);
                f.IsDirectory = false;
                if (arr[3].IndexOf(".") > -1) f.FileType = arr[3].Split('.')[1];
                else f.FileType = "未知";
            }
            return f;
        }

        private FileStruct ParseFileStructFromUnixStyleRecord(string record)
        {
            ///Assuming record style as
            /// dr-xr-xr-x   1 owner    group               0 Nov 25  2002 bussys
            FileStruct f = new FileStruct();
            if (record[0] == '-' || record[0] == 'd')
            {// its a valid file record
                string processstr = record.Trim();
                var flag = processstr.Substring(0, 9);
                f.IsDirectory = (flag[0] == 'd');
                processstr = (processstr.Substring(11)).Trim();
                _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);   //skip one part
                f.Owner = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);
                f.CreateTime = getCreateTimeString(record);
                int fileNameIndex = record.IndexOf(f.CreateTime) + f.CreateTime.Length;
                f.Name = record.Substring(fileNameIndex).Trim();   //Rest of the part is name
            }
            else f.Name = string.Empty;
            return f;
        }

        private string getCreateTimeString(string record)
        {
            //Does just basic datetime string validation for demo, not an accurate check
            //on date and time fields
            string month = "(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)";
            string space = @"(\040)+";
            string day = "([0-9]|[1-3][0-9])";
            string year = "[1-2][0-9]{3}";
            string time = "[0-9]{1,2}:[0-9]{2}";
            Regex dateTimeRegex = new Regex(month + space + day + space + "(" + year + "|" + time + ")", RegexOptions.IgnoreCase);
            Match match = dateTimeRegex.Match(record);
            return match.Value;
        }

        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;
        }
    }
}

 

posted on 2020-06-02 15:18  所谓的潇洒  阅读(503)  评论(0编辑  收藏  举报