C# FTP操作

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Net;
  4 using System.IO;
  5 
  6 namespace FTP操作
  7 {
  8     /// <summary>
  9     /// FTP客户端操作类
 10     /// </summary>
 11     public class FtpClient
 12     {
 13         #region 构造函数
 14         /// <summary>
 15         /// 创建FTP工具
 16         /// <para>
 17         /// 默认不使用SSL,使用二进制传输方式,使用被动模式
 18         /// </para>
 19         /// </summary>
 20         /// <param name="host">主机名称</param>
 21         /// <param name="userId">用户名</param>
 22         /// <param name="password">密码</param>
 23         public FtpClient(string host, string userId, string password)
 24             : this(host, userId, password, 21, null, false, true, true)
 25         {
 26         }
 27 
 28         /// <summary>
 29         /// 创建FTP工具
 30         /// </summary>
 31         /// <param name="host">主机名称</param>
 32         /// <param name="userId">用户名</param>
 33         /// <param name="password">密码</param>
 34         /// <param name="port">端口</param>
 35         /// <param name="enableSsl">允许Ssl</param>
 36         /// <param name="proxy">代理</param>
 37         /// <param name="useBinary">允许二进制</param>
 38         /// <param name="usePassive">允许被动模式</param>
 39         public FtpClient(string host, string userId, string password, int port, IWebProxy proxy, bool enableSsl, bool useBinary, bool usePassive)
 40         {
 41             this.userId = userId;
 42             this.password = password;
 43             if (host.ToLower().StartsWith("ftp://"))
 44             {
 45                 this.host = host;
 46             }
 47             else
 48             {
 49                 this.host = "ftp://" + host;
 50             }
 51             this.port = port;
 52             this.proxy = proxy;
 53             this.enableSsl = enableSsl;
 54             this.useBinary = useBinary;
 55             this.usePassive = usePassive;
 56         }
 57         #endregion
 58 
 59         #region 主机
 60         private string host = string.Empty;
 61         /// <summary>
 62         /// 主机
 63         /// </summary>
 64         public string Host
 65         {
 66             get
 67             {
 68                 return this.host ?? string.Empty;
 69             }
 70         }
 71         #endregion
 72 
 73         #region 登录用户名
 74         private string userId = string.Empty;
 75         /// <summary>
 76         /// 登录用户名
 77         /// </summary>
 78         public string UserId
 79         {
 80             get
 81             {
 82                 return this.userId;
 83             }
 84         }
 85         #endregion
 86 
 87         #region 密码
 88         private string password = string.Empty;
 89         /// <summary>
 90         /// 密码
 91         /// </summary>
 92         public string Password
 93         {
 94             get
 95             {
 96                 return this.password;
 97             }
 98         }
 99         #endregion
100 
101         #region 代理
102         IWebProxy proxy = null;
103         /// <summary>
104         /// 代理
105         /// </summary>
106         public IWebProxy Proxy
107         {
108             get
109             {
110                 return this.proxy;
111             }
112             set
113             {
114                 this.proxy = value;
115             }
116         }
117         #endregion
118 
119         #region 端口
120         private int port = 21;
121         /// <summary>
122         /// 端口
123         /// </summary>
124         public int Port
125         {
126             get
127             {
128                 return port;
129             }
130             set
131             {
132                 this.port = value;
133             }
134         }
135         #endregion
136 
137         #region 设置是否允许Ssl
138         private bool enableSsl = false;
139         /// <summary>
140         /// EnableSsl 
141         /// </summary>
142         public bool EnableSsl
143         {
144             get
145             {
146                 return enableSsl;
147             }
148         }
149         #endregion
150 
151         #region 使用被动模式
152         private bool usePassive = true;
153         /// <summary>
154         /// 被动模式
155         /// </summary>
156         public bool UsePassive
157         {
158             get
159             {
160                 return usePassive;
161             }
162             set
163             {
164                 this.usePassive = value;
165             }
166         }
167         #endregion
168 
169         #region 二进制方式
170         private bool useBinary = true;
171         /// <summary>
172         /// 二进制方式
173         /// </summary>
174         public bool UseBinary
175         {
176             get
177             {
178                 return useBinary;
179             }
180             set
181             {
182                 this.useBinary = value;
183             }
184         }
185         #endregion
186 
187         #region 远端路径
188         private string remotePath = "/";
189         /// <summary>
190         /// 远端路径
191         /// <para>
192         ///     返回FTP服务器上的当前路径(可以是 / 或 /a/../ 的形式)
193         /// </para>
194         /// </summary>
195         public string RemotePath
196         {
197             get
198             {
199                 return remotePath;
200             }
201             set
202             {
203                 string result = "/";
204                 if (!string.IsNullOrEmpty(value) && value != "/")
205                 {
206                     result = "/" + value.TrimStart('/').TrimEnd('/') + "/";
207                 }
208                 this.remotePath = result;
209             }
210         }
211         #endregion
212 
213         #region 创建一个FTP连接
214         /// <summary>
215         /// 创建一个FTP请求
216         /// </summary>
217         /// <param name="url">请求地址</param>
218         /// <param name="method">请求方法</param>
219         /// <returns>FTP请求</returns>
220         private FtpWebRequest CreateRequest(string url, string method)
221         {
222             //建立连接
223             FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
224             request.Credentials = new NetworkCredential(this.userId, this.password);
225             request.Proxy = this.proxy;
226             request.KeepAlive = false;//命令执行完毕之后关闭连接
227             request.UseBinary = useBinary;
228             request.UsePassive = usePassive;
229             request.EnableSsl = enableSsl;
230             request.Method = method;
231             return request;
232         }
233         #endregion
234 
235         #region 上传一个文件到远端路径下
236         /// <summary>
237         /// 把文件上传到FTP服务器的RemotePath下
238         /// </summary>
239         /// <param name="localFile">本地文件信息</param>
240         /// <param name="remoteFileName">要保存到FTP文件服务器上的名称</param>
241         public bool Upload(FileInfo localFile, string remoteFileName)
242         {
243             bool result = false;
244             if (localFile.Exists)
245             {
246                 string url = Host.TrimEnd('/') + RemotePath + remoteFileName;
247                 FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.UploadFile);
248 
249                 //上传数据
250                 using (Stream rs = request.GetRequestStream())
251                 using (FileStream fs = localFile.OpenRead())
252                 {
253                     byte[] buffer = new byte[4096];//4K
254                     int count = fs.Read(buffer, 0, buffer.Length);
255                     while (count > 0)
256                     {
257                         rs.Write(buffer, 0, count);
258                         count = fs.Read(buffer, 0, buffer.Length);
259                     }
260                     fs.Close();
261                     result = true;
262                 }
263                 return result;
264             }
265             throw new Exception(string.Format("本地文件不存在,文件路径:{0}", localFile.FullName));
266         }
267         #endregion
268 
269         #region 从FTP服务器上下载文件
270         /// <summary>
271         /// 从当前目录下下载文件
272         /// <para>
273         /// 如果本地文件存在,则从本地文件结束的位置开始下载.
274         /// </para>
275         /// </summary>
276         /// <param name="serverName">服务器上的文件名称</param>
277         /// <param name="localName">本地文件名称</param>
278         /// <returns>返回一个值,指示是否下载成功</returns>
279         public bool Download(string serverName, string localName)
280         {
281             bool result = false;
282             using (FileStream fs = new FileStream(localName, FileMode.OpenOrCreate)) //创建或打开本地文件
283             {
284                 //建立连接
285                 string url = Host.TrimEnd('/') + RemotePath + serverName;
286                 FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.DownloadFile);
287                 request.ContentOffset = fs.Length;
288                 using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
289                 {
290                     fs.Position = fs.Length;
291                     byte[] buffer = new byte[4096];//4K
292                     int count = response.GetResponseStream().Read(buffer, 0, buffer.Length);
293                     while (count > 0)
294                     {
295                         fs.Write(buffer, 0, count);
296                         count = response.GetResponseStream().Read(buffer, 0, buffer.Length);
297                     }
298                     response.GetResponseStream().Close();
299                 }
300                 result = true;
301             }
302             return result;
303         }
304         #endregion
305 
306         #region 重命名FTP服务器上的文件
307         /// <summary>
308         /// 文件更名
309         /// </summary>
310         /// <param name="oldFileName">原文件名</param>
311         /// <param name="newFileName">新文件名</param>
312         /// <returns>返回一个值,指示更名是否成功</returns>
313         public bool Rename(string oldFileName, string newFileName)
314         {
315             bool result = false;
316             //建立连接
317             string url = Host.TrimEnd('/') + RemotePath + oldFileName;
318             FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.Rename);
319             request.RenameTo = newFileName;
320             using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
321             {
322                 result = true;
323             }
324             return result;
325         }
326         #endregion
327 
328         #region 从当前目录下获取文件列表
329         /// <summary>
330         /// 获取当前目录下文件列表
331         /// </summary>
332         /// <returns></returns>
333         public List<string> GetFileList()
334         {
335             List<string> result = new List<string>();
336             //建立连接
337             string url = Host.TrimEnd('/') + RemotePath;
338             FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.ListDirectory);
339             using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
340             {
341                 StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default);//中文文件名
342                 string line = reader.ReadLine();
343                 while (line != null)
344                 {
345                     result.Add(line);
346                     line = reader.ReadLine();
347                 }
348             }
349             return result;
350         }
351         #endregion
352 
353         #region 从FTP服务器上获取文件和文件夹列表
354         /// <summary>
355         /// 获取详细列表
356         /// </summary>
357         /// <returns></returns>
358         public List<string> GetFileDetails()
359         {
360             List<string> result = new List<string>();
361             //建立连接
362             string url = Host.TrimEnd('/') + RemotePath;
363             FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.ListDirectoryDetails);
364             using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
365             {
366                 StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default);//中文文件名
367                 string line = reader.ReadLine();
368                 while (line != null)
369                 {
370                     result.Add(line);
371                     line = reader.ReadLine();
372                 }
373             }
374             return result;
375         }
376         #endregion
377 
378         #region 从FTP服务器上删除文件
379         /// <summary>
380         /// 删除FTP服务器上的文件
381         /// </summary>
382         /// <param name="fileName">文件名称</param>
383         /// <returns>返回一个值,指示是否删除成功</returns>
384         public bool DeleteFile(string fileName)
385         {
386             bool result = false;
387             //建立连接
388             string url = Host.TrimEnd('/') + RemotePath + fileName;
389             FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.DeleteFile);
390             using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
391             {
392                 result = true;
393             }
394 
395             return result;
396         }
397         #endregion
398 
399         #region 在FTP服务器上创建目录
400         /// <summary>
401         /// 在当前目录下创建文件夹
402         /// </summary>
403         /// <param name="dirName">文件夹名称</param>
404         /// <returns>返回一个值,指示是否创建成功</returns>
405         public bool MakeDirectory(string dirName)
406         {
407             bool result = false;
408             //建立连接
409             string url = Host.TrimEnd('/') + RemotePath + dirName;
410             FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.MakeDirectory);
411             using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
412             {
413                 result = true;
414             }
415             return result;
416         }
417         #endregion
418 
419         #region 从FTP服务器上删除目录
420         /// <summary>
421         /// 删除文件夹
422         /// </summary>
423         /// <param name="dirName">文件夹名称</param>
424         /// <returns>返回一个值,指示是否删除成功</returns>
425         public bool DeleteDirectory(string dirName)
426         {
427             bool result = false;
428             //建立连接
429             string url = Host.TrimEnd('/') + RemotePath + dirName;
430             FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.RemoveDirectory);
431             using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
432             {
433                 result = true;
434             }
435             return result;
436         }
437         #endregion
438 
439         #region 从FTP服务器上获取文件大小
440         /// <summary>
441         /// 获取文件大小
442         /// </summary>
443         /// <param name="fileName"></param>
444         /// <returns></returns>
445         public long GetFileSize(string fileName)
446         {
447             long result = 0;
448             //建立连接
449             string url = Host.TrimEnd('/') + RemotePath + fileName;
450             FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.GetFileSize);
451             using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
452             {
453                 result = response.ContentLength;
454             }
455 
456             return result;
457         }
458         #endregion
459 
460         #region 给FTP服务器上的文件追加内容
461         /// <summary>
462         /// 给FTP服务器上的文件追加内容
463         /// </summary>
464         /// <param name="localFile">本地文件</param>
465         /// <param name="remoteFileName">FTP服务器上的文件</param>
466         /// <returns>返回一个值,指示是否追加成功</returns>
467         public bool Append(FileInfo localFile, string remoteFileName)
468         {
469             if (localFile.Exists)
470             {
471                 using (FileStream fs = new FileStream(localFile.FullName, FileMode.Open))
472                 {
473                     return Append(fs, remoteFileName);
474                 }
475             }
476             throw new Exception(string.Format("本地文件不存在,文件路径:{0}", localFile.FullName));
477         }
478 
479         /// <summary>
480         /// 给FTP服务器上的文件追加内容
481         /// </summary>
482         /// <param name="stream">数据流(可通过设置偏移来实现从特定位置开始上传)</param>
483         /// <param name="remoteFileName">FTP服务器上的文件</param>
484         /// <returns>返回一个值,指示是否追加成功</returns>
485         public bool Append(Stream stream, string remoteFileName)
486         {
487             bool result = false;
488             if (stream != null && stream.CanRead)
489             {
490                 //建立连接
491                 string url = Host.TrimEnd('/') + RemotePath + remoteFileName;
492                 FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.AppendFile);
493                 using (Stream rs = request.GetRequestStream())
494                 {
495                     //上传数据
496                     byte[] buffer = new byte[4096];//4K
497                     int count = stream.Read(buffer, 0, buffer.Length);
498                     while (count > 0)
499                     {
500                         rs.Write(buffer, 0, count);
501                         count = stream.Read(buffer, 0, buffer.Length);
502                     }
503                     result = true;
504                 }
505             }
506             return result;
507         }
508         #endregion
509 
510         #region 获取FTP服务器上的当前路径
511         /// <summary>
512         /// 获取FTP服务器上的当前路径
513         /// </summary>
514         public string CurrentDirectory
515         {
516             get
517             {
518                 string result = string.Empty;
519                 string url = Host.TrimEnd('/') + RemotePath;
520                 FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.PrintWorkingDirectory);
521                 using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
522                 {
523                     string temp = response.StatusDescription;
524                     int start = temp.IndexOf('"') + 1;
525                     int end = temp.LastIndexOf('"');
526                     if (end >= start)
527                     {
528                         result = temp.Substring(start, end - start);
529                     }
530                 }
531                 return result;
532 
533             }
534         }
535         #endregion
536 
537         #region 检查当前路径上是否存在某个文件
538         /// <summary>
539         /// 检查文件是否存在
540         /// </summary>
541         /// <param name="fileName">要检查的文件名</param>
542         /// <returns>返回一个值,指示要检查的文件是否存在</returns>
543         public bool CheckFileExist(string fileName)
544         {
545             bool result = false;
546             if (fileName != null && fileName.Trim().Length > 0)
547             {
548                 fileName = fileName.Trim();
549                 List<string> files = GetFileList();
550                 if (files != null && files.Count > 0)
551                 {
552                     foreach (string file in files)
553                     {
554                         if (file.ToLower() == fileName.ToLower())
555                         {
556                             result = true;
557                             break;
558                         }
559                     }
560                 }
561             }
562             return result;
563         }
564         #endregion
565 
566     }
567 }
568 
569 /*
570 FTP全状态码查询词典
571   
572 1xx - 肯定的初步答复
573 这些状态代码指示一项操作已经成功开始,但客户端希望在继续操作新命令前得到另一个答复。 • 110 重新启动标记答复。 
574 • 120 服务已就绪,在 nnn 分钟后开始。 
575 • 125 数据连接已打开,正在开始传输。 
576 • 150 文件状态正常,准备打开数据连接。 
577 
578 2xx - 肯定的完成答复
579 一项操作已经成功完成。客户端可以执行新命令。 • 200 命令确定。 
580 • 202 未执行命令,站点上的命令过多。 
581 • 211 系统状态,或系统帮助答复。 
582 • 212 目录状态。 
583 • 213 文件状态。 
584 • 214 帮助消息。 
585 • 215 NAME 系统类型,其中,NAME 是 Assigned Numbers 文档中所列的正式系统名称。 
586 • 220 服务就绪,可以执行新用户的请求。 
587 • 221 服务关闭控制连接。如果适当,请注销。 
588 • 225 数据连接打开,没有进行中的传输。 
589 • 226 关闭数据连接。请求的文件操作已成功(例如,传输文件或放弃文件)。 
590 • 227 进入被动模式 (h1,h2,h3,h4,p1,p2)。 
591 • 230 用户已登录,继续进行。 
592 • 250 请求的文件操作正确,已完成。 
593 • 257 已创建“PATHNAME”。 
594 
595 3xx - 肯定的中间答复
596 该命令已成功,但服务器需要更多来自客户端的信息以完成对请求的处理。 • 331 用户名正确,需要密码。 
597 • 332 需要登录帐户。 
598 • 350 请求的文件操作正在等待进一步的信息。 
599 
600 4xx - 瞬态否定的完成答复
601 该命令不成功,但错误是暂时的。如果客户端重试命令,可能会执行成功。 • 421 服务不可用,正在关闭控制连接。如果服务确定它必须关闭,将向任何命令发送这一应答。 
602 • 425 无法打开数据连接。 
603 • 426 Connection closed; transfer aborted. 
604 • 450 未执行请求的文件操作。文件不可用(例如,文件繁忙)。 
605 • 451 请求的操作异常终止:正在处理本地错误。 
606 • 452 未执行请求的操作。系统存储空间不够。 
607 
608 5xx - 永久性否定的完成答复
609 该命令不成功,错误是永久性的。如果客户端重试命令,将再次出现同样的错误。 • 500 语法错误,命令无法识别。这可能包括诸如命令行太长之类的错误。 
610 • 501 在参数中有语法错误。 
611 • 502 未执行命令。 
612 • 503 错误的命令序列。 
613 • 504 未执行该参数的命令。 
614 • 530 未登录。 
615 • 532 存储文件需要帐户。 
616 • 550 未执行请求的操作。文件不可用(例如,未找到文件,没有访问权限)。 
617 • 551 请求的操作异常终止:未知的页面类型。 
618 • 552 请求的文件操作异常终止:超出存储分配(对于当前目录或数据集)。 
619 • 553 未执行请求的操作。不允许的文件名。 
620 常见的 FTP 状态代码及其原因
621 • 150 - FTP 使用两个端口:21 用于发送命令,20 用于发送数据。状态代码 150 表示服务器准备在端口 20 上打开新连接,发送一些数据。 
622 • 226 - 命令在端口 20 上打开数据连接以执行操作,如传输文件。该操作成功完成,数据连接已关闭。 
623 • 230 - 客户端发送正确的密码后,显示该状态代码。它表示用户已成功登录。 
624 • 331 - 客户端发送用户名后,显示该状态代码。无论所提供的用户名是否为系统中的有效帐户,都将显示该状态代码。 
625 • 426 - 命令打开数据连接以执行操作,但该操作已被取消,数据连接已关闭。 
626 • 530 - 该状态代码表示用户无法登录,因为用户名和密码组合无效。如果使用某个用户帐户登录,可能键入错误的用户名或密码,也可能选择只允许匿名访问。如果使用匿名帐户登录,IIS 的配置可能拒绝匿名访问。 
627 • 550 - 命令未被执行,因为指定的文件不可用。例如,要 GET 的文件并不存在,或试图将文件 PUT 到您没有写入权限的目录。
628 */

 

posted @ 2013-09-26 09:03  skynetfy  阅读(2035)  评论(0编辑  收藏  举报