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