上篇文章讨论了C#从基于FTPS的FTP server下载数据 (FtpWebRequest 的使用)SSL 加密。不过细心的朋友应该可以发现FTPWebRequest 每次都是新生成一个request ( FTPWebRequest.create(uri) ), 这样对于一些复杂的需求,需要反复登陆,代码就会变得冗余啰嗦,那今天就和大家探讨一下如何包装FTPWebRequest类。如有好的想法或意见,希望各位大神老鸟多多指教。
先说一下我的需求:
去FTP Server 的一个指定路径下,找到更新时间最近的文件并下载。
那按照以上需求,就需要先去路径下,找到更新时间最近的文件,在根据文件名下载。
这里封装一个FTPClient 类 (从网上找了一个FTPClient的壳子,忘记了原博客地址了,抱歉)
原理很简单,就是封装‘列出目录功能’和 ‘下载文件功能’。将用户名密码等放在FTPClient的属性中。
上码!
1 using System.Collections.Generic; 2 using System; 3 using System.Net; 4 using System.IO; 5 using System.Security.Cryptography.X509Certificates; 6 using System.Net.Security; 7 8 namespace FtpClientBlogCase 9 { 10 11 12 #region "FTP client class" 13 public class FTPclient 14 { 15 #region "CONSTRUCTORS" 16 public FTPclient(string Hostname, string Username, string Password, bool EnableSSL) 17 { 18 this.Hostname = Hostname; 19 this.Username = Username; 20 this.Password = Password; 21 this.EnableSsl = EnableSSL; 22 } 23 #endregion 24 25 #region "Directory functions" 26 public List<string> ListDirectory(string URI) 27 { 28 System.Net.FtpWebRequest ftp = GetRequest(URI); 29 //Set request to do simple list 30 ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectory; 31 32 string str = GetStringResponse(ftp); 33 //replace CRLF to CR, remove last instance 34 str = str.Replace("\r\n", "\r").TrimEnd(‘\r‘); 35 //split the string into a list 36 List<string> result = new List<string>(); 37 result.AddRange(str.Split(‘\r‘)); 38 return result; 39 } 40 #endregion 41 42 #region "Download: File transfer FROM ftp server" 43 /// <summary> 44 /// Copy a file from FTP server to local 45 /// </summary> 46 /// <param name="sourceFilename">Target filename, if required</param> 47 /// <param name="localFilename">Full path of the local file</param> 48 /// <returns></returns> 49 /// <remarks> 50 /// Target can be blank (use same filename), or just a filename 51 /// (assumes current directory) or a full path and filename 52 /// 1.2 [HR] added CreateURI 53 /// </remarks> 54 public bool Download(string sourceFilename, string localFilename, bool PermitOverwrite) 55 { 56 //2. determine target file 57 FileInfo fi = new FileInfo(localFilename); 58 return this.Download(sourceFilename, fi, PermitOverwrite); 59 } 60 61 /// <summary> 62 /// Version taking string/FileInfo 63 /// </summary> 64 /// <param name="sourceFilename"></param> 65 /// <param name="targetFI"></param> 66 /// <param name="PermitOverwrite"></param> 67 /// <returns></returns> 68 public bool Download(string sourceFilename, FileInfo targetFI, bool PermitOverwrite) 69 { 70 //1. check target 71 if (targetFI.Exists && !(PermitOverwrite)) 72 { 73 throw (new ApplicationException("Target file already exists")); 74 } 75 76 //2. check source 77 if (String.IsNullOrEmpty(sourceFilename)) 78 { 79 throw (new ApplicationException("File not specified")); 80 } 81 System.Net.FtpWebRequest ftp = GetRequest(sourceFilename); 82 83 //Set request to download a file in binary mode 84 ftp.Method = System.Net.WebRequestMethods.Ftp.DownloadFile; 85 ftp.UseBinary = true; 86 87 //open request and get response stream 88 using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse()) 89 { 90 using (Stream responseStream = response.GetResponseStream()) 91 { 92 //loop to read & write to file 93 responseStream.ReadTimeout = 600000; 94 using (FileStream fs = targetFI.OpenWrite()) 95 { 96 try 97 { 98 byte[] buffer = new byte[2048*1000*2]; 99 int read = 0; 100 do 101 { 102 read = responseStream.Read(buffer, 0, buffer.Length); 103 fs.Write(buffer, 0, read); 104 fs.Flush(); 105 } while (read != 0); 106 responseStream.Close(); 107 fs.Flush(); 108 fs.Close(); 109 } 110 catch (Exception) 111 { 112 //catch error and delete file only partially downloaded 113 fs.Close(); 114 //delete target file as it‘s incomplete 115 targetFI.Delete(); 116 throw; 117 } 118 } 119 120 responseStream.Close(); 121 } 122 123 response.Close(); 124 } 125 126 127 return true; 128 } 129 130 #endregion 131 132 #region "private supporting fns" 133 134 135 //Get the basic FtpWebRequest object with the 136 //common settings and security 137 private FtpWebRequest GetRequest(string URI) 138 { 139 //create request 140 FtpWebRequest result = (FtpWebRequest)FtpWebRequest.Create(URI); 141 //Set the login details 142 result.Credentials = GetCredentials(); 143 // support for EnableSSL 144 result.EnableSsl = EnableSsl; 145 result.Timeout = 600000; 146 147 ServicePoint sp = result.ServicePoint; 148 ServicePointManager.ServerCertificateValidationCallback = 149 new RemoteCertificateValidationCallback(ValidateServerCertificate); 150 151 return result; 152 } 153 154 /// <summary> 155 /// Ensure chars in path are correctly escaped e.g. # 156 /// </summary> 157 /// <param name="path">path to escape</param> 158 /// <returns></returns> 159 private string GetEscapedPath(string path) 160 { 161 string[] parts; 162 parts = path.Split(‘/‘); 163 string result; 164 result = ""; 165 foreach (string part in parts) 166 { 167 if (!string.IsNullOrEmpty(part)) 168 result += @"/" + Uri.EscapeDataString(part); 169 } 170 return result; 171 } 172 173 174 /// <summary> 175 /// Get the credentials from username/password 176 /// </summary> 177 /// <remarks> 178 /// Amended to store credentials on first use, for re-use 179 /// when using KeepAlive=true 180 /// </remarks> 181 private System.Net.ICredentials GetCredentials() 182 { 183 if (_credentials == null) 184 _credentials = new System.Net.NetworkCredential(Username, Password); 185 return _credentials; 186 } 187 188 /// <summary> 189 /// stored credentials 190 /// </summary> 191 private System.Net.NetworkCredential _credentials = null; 192 193 194 195 /// <summary> 196 /// Obtains a response stream as a string 197 /// </summary> 198 /// <param name="ftp">current FTP request</param> 199 /// <returns>String containing response</returns> 200 /// <remarks> 201 /// FTP servers typically return strings with CR and 202 /// not CRLF. Use respons.Replace(vbCR, vbCRLF) to convert 203 /// to an MSDOS string 204 /// 1.1: modified to ensure accepts UTF8 encoding 205 /// </remarks> 206 private string GetStringResponse(FtpWebRequest ftp) 207 { 208 //Get the result, streaming to a string 209 string result = ""; 210 using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse()) 211 { 212 long size = response.ContentLength; 213 using (Stream datastream = response.GetResponseStream()) 214 { 215 using (StreamReader sr = new StreamReader(datastream, System.Text.Encoding.UTF8)) 216 { 217 result = sr.ReadToEnd(); 218 sr.Close(); 219 } 220 221 datastream.Close(); 222 } 223 224 response.Close(); 225 } 226 227 return result; 228 } 229 230 /// <summary> 231 /// Gets the size of an FTP request 232 /// </summary> 233 /// <param name="ftp"></param> 234 /// <returns></returns> 235 /// <remarks></remarks> 236 private long GetSize(FtpWebRequest ftp) 237 { 238 long size; 239 using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse()) 240 { 241 size = response.ContentLength; 242 response.Close(); 243 } 244 245 return size; 246 } 247 248 private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) 249 { 250 return true; 251 } 252 253 254 255 #endregion 256 257 #region Properties 258 259 public string Hostname { get; set; } 260 public string Username { get; set; } 261 public string Password { get; set; } 262 public bool EnableSsl { get; set; } 263 264 #endregion 265 266 } 267 #endregion 268 269 270 }
FTPClient.cs
1 using System; 2 using System.Configuration; 3 using System.Linq; 4 5 namespace FtpClientBlogCase 6 { 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 DownloadFileFromFTP.DownloadFileFromNetwork(); 12 Console.WriteLine("Done"); 13 } 14 } 15 16 public class DownloadFileFromFTP 17 { 18 public static void DownloadFileFromNetwork() 19 { 20 var fullDataServer = "XXX"; 21 var userName = "XXX"; 22 var password = "XXX"; 23 var fc = new FTPclient(fullDataServer, userName, password, true); 24 var list = fc.ListDirectory(fullDataServer); 25 Console.WriteLine("The file is downloading, please wait..."); 26 fc.Download(fullDataServer + list.Last(), list.Last(), true); 27 28 } 29 } 30 }
Program.cs
在类FTPClient中,private FtpWebRequest GetRequest(string URI) 是最重要的方法,它为每一个功能提供了一个FtpWebRequest对象,避免了每次生成request对象的冗余冗余代码。
时间: 2024-10-13 10:07:57