|
最近在搞FTP,挺头大的,后来索性在网上找了个FTP的类,直接调用函数即可。由于网上的版本较多,我用的这个测试了下,比较好用。现共享给大家。
1 using System;
2 using System.Net;
3 using System.IO;
4 using System.Text;
5 using System.Net.Sockets;
6
7 namespace WindowsFormsApplication1
8 {
9 public class FTPClient
10 {
11 #region 构造函数
12 ///
13 /// 缺省构造函数
14 ///
15 public FTPClient()
16 {
17 strRemoteHost = "";
18 strRemotePath = "";
19 strRemoteUser = "";
20 strRemotePass = "";
21 strRemotePort = 21;
22 bConnected = false;
23 }
24
25 ///
26 /// 构造函数
27 ///
28 ///
29 ///
30 ///
31 ///
32 ///
33 public FTPClient(string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort)
34 {
35 strRemoteHost = remoteHost;
36 strRemotePath = remotePath;
37 strRemoteUser = remoteUser;
38 strRemotePass = remotePass;
39 strRemotePort = remotePort;
40 Connect();
41 }
42 #endregion
43
44 #region 登陆
45 ///
46 /// FTP服务器IP地址
47 ///
48 private string strRemoteHost;
49 public string RemoteHost
50 {
51 get
52 {
53 return strRemoteHost;
54 }
55 set
56 {
57 strRemoteHost = value;
58 }
59 }
60 ///
61 /// FTP服务器端口
62 ///
63 private int strRemotePort;
64 public int RemotePort
65 {
66 get
67 {
68 return strRemotePort;
69 }
70 set
71 {
72 strRemotePort = value;
73 }
74 }
75 ///
76 /// 当前服务器目录
77 ///
78 private string strRemotePath;
79 public string RemotePath
80 {
81 get
82 {
83 return strRemotePath;
84 }
85 set
86 {
87 strRemotePath = value;
88 }
89 }
90 ///
91 /// 登录用户账号
92 ///
93 private string strRemoteUser;
94 public string RemoteUser
95 {
96 set
97 {
98 strRemoteUser = value;
99 }
100 }
101 ///
102 /// 用户登录密码
103 ///
104 private string strRemotePass;
105 public string RemotePass
106 {
107 set
108 {
109 strRemotePass = value;
110 }
111 }
112
113 ///
114 /// 是否登录
115 ///
116 private Boolean bConnected;
117 public bool Connected
118 {
119 get
120 {
121 return bConnected;
122 }
123 }
124 #endregion
125
126 #region 链接
127 ///
128 /// 建立连接
129 ///
130 public void Connect()
131 {
132 socketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
133 IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), strRemotePort);
134 // 链接
135 try
136 {
137 socketControl.Connect(ep);
138 }
139 catch (Exception)
140 {
141 throw new IOException("Couldn't connect to remote server");
142 }
143
144 // 获取应答码
145 ReadReply();
146 if (iReplyCode != 220)
147 {
148 DisConnect();
149 throw new IOException(strReply.Substring(4));
150 }
151
152 // 登陆
153 SendCommand("USER " + strRemoteUser);
154 if (!(iReplyCode == 331 || iReplyCode == 230))
155 {
156 CloseSocketConnect();//关闭连接
157 throw new IOException(strReply.Substring(4));
158 }
159 if (iReplyCode != 230)
160 {
161 SendCommand("PASS " + strRemotePass);
162 if (!(iReplyCode == 230 || iReplyCode == 202))
163 {
164 CloseSocketConnect();//关闭连接
165 throw new IOException(strReply.Substring(4));
166 }
167 }
168 bConnected = true;
169
170 // 切换到目录
171 ChDir(strRemotePath);
172 }
173
174
175 ///
176 /// 关闭连接
177 ///
178 public void DisConnect()
179 {
180 if (socketControl != null)
181 {
182 SendCommand("QUIT");
183 }
184 CloseSocketConnect();
185 }
186
187 #endregion
188
189 #region 传输模式
190
191 ///
192 /// 传输模式:二进制类型、ASCII类型
193 ///
194 public enum TransferType { Binary, ASCII };
195
196 ///
197 /// 设置传输模式
198 ///
199 /// 传输模式
200 public void SetTransferType(TransferType ttType)
201 {
202 if (ttType == TransferType.Binary)
203 {
204 SendCommand("TYPE I");//binary类型传输
205 }
206 else
207 {
208 SendCommand("TYPE A");//ASCII类型传输
209 }
210 if (iReplyCode != 200)
211 {
212 throw new IOException(strReply.Substring(4));
213 }
214 else
215 {
216 trType = ttType;
217 }
218 }
219
220
221 ///
222 /// 获得传输模式
223 ///
224 /// 传输模式
225 public TransferType GetTransferType()
226 {
227 return trType;
228 }
229
230 #endregion
231
232 #region 文件操作
233 ///
234 /// 获得文件列表
235 ///
236 /// 文件名的匹配字符串
237 ///
238 public string[] Dir(string strMask)
239 {
240 // 建立链接
241 if (!bConnected)
242 {
243 Connect();
244 }
245
246 //建立进行数据连接的socket
247 Socket socketData = CreateDataSocket();
248
249 //传送命令
250 SendCommand("NLST " + strMask);
251
252 //分析应答代码
253 if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226))
254 {
255 throw new IOException(strReply.Substring(4));
256 }
257
258 //获得结果
259 strMsg = "";
260 while (true)
261 {
262 int iBytes = socketData.Receive(buffer, buffer.Length, 0);
263 strMsg += Encoding.Default.GetString(buffer, 0, iBytes);
264 if (iBytes < buffer.Length)
265 {
266 break;
267 }
268 }
269 char[] seperator = "\r\n".ToCharArray();
270 string[] strsFileList = strMsg.Split(seperator, StringSplitOptions.RemoveEmptyEntries);
271 socketData.Close();//数据socket关闭时也会有返回码
272 if (iReplyCode != 226)
273 {
274 ReadReply();
275 if (iReplyCode != 226)
276 {
277 throw new IOException(strReply.Substring(4));
278 }
279 }
280 return strsFileList;
281 }
282
283
284 ///
285 /// 获取文件大小
286 ///
287 /// 文件名
288 /// 文件大小
289 private long GetFileSize(string strFileName)
290 {
291 if (!bConnected)
292 {
293 Connect();
294 }
295 SendCommand("SIZE " + Path.GetFileName(strFileName));
296 long lSize = 0;
297 if (iReplyCode == 213)
298 {
299 lSize = Int64.Parse(strReply.Substring(4));
300 }
301 else
302 {
303 throw new IOException(strReply.Substring(4));
304 }
305 return lSize;
306 }
307
308 ///
309 /// 获得文件详细信息列表
310 ///
311 /// 文件名的匹配字符串
312 ///
313 public string[] List(string strMask)
314 {
315 // 建立链接
316 if (!bConnected)
317 {
318 Connect();
319 }
320
321 //建立进行数据连接的socket
322 Socket socketData = CreateDataSocket();
323
324 //传送命令
325 SendCommand("LIST " + strMask);
326
327 //分析应答代码
328 if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226))
329 {
330 throw new IOException(strReply.Substring(4));
331 }
332
333 //获得结果
334 strMsg = "";
335 while (true)
336 {
337 int iBytes = socketData.Receive(buffer, buffer.Length, 0);
338 strMsg += Encoding.Default.GetString(buffer, 0, iBytes);
339 if (iBytes < buffer.Length)
340 {
341 break;
342 }
343 }
344 char[] seperator = "\r\n".ToCharArray();
345 string[] strsFileList = strMsg.Split(seperator, StringSplitOptions.RemoveEmptyEntries);
346 socketData.Close();//数据socket关闭时也会有返回码
347 if (iReplyCode != 226)
348 {
349 ReadReply();
350 if (iReplyCode != 226)
351 {
352 throw new IOException(strReply.Substring(4));
353 }
354 }
355 return strsFileList;
356 }
357
358
359 ///
360 /// 删除
361 ///
362 /// 待删除文件名
363 public void Delete(string strFileName)
364 {
365 if (!bConnected)
366 {
367 Connect();
368 }
369 SendCommand("DELE " + strFileName);
370 if (iReplyCode != 250)
371 {
372 throw new IOException(strReply.Substring(4));
373 }
374 }
375
376
377 ///
378 /// 重命名(如果新文件名与已有文件重名,将覆盖已有文件)
379 ///
380 /// 旧文件名
381 /// 新文件名
382 public void Rename(string strOldFileName, string strNewFileName)
383 {
384 if (!bConnected)
385 {
386 Connect();
387 }
388 SendCommand("RNFR " + strOldFileName);
389 if (iReplyCode != 350)
390 {
391 throw new IOException(strReply.Substring(4));
392 }
393 // 如果新文件名与原有文件重名,将覆盖原有文件
394 SendCommand("RNTO " + strNewFileName);
395 if (iReplyCode != 250)
396 {
397 throw new IOException(strReply.Substring(4));
398 }
399 }
400 #endregion
401
402 #region 上传和下载
403 ///
404 /// 下载一批文件
405 ///
406 /// 文件名的匹配字符串
407 /// 本地目录(不得以\结束)
408 public void Get(string strFileNameMask, string strFolder)
409 {
410 if (!bConnected)
411 {
412 Connect();
413 }
414 string[] strFiles = Dir(strFileNameMask);
415 foreach (string strFile in strFiles)
416 {
417 if (!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是空字符串
418 {
419 Get(strFile, strFolder, strFile);
420 }
421 }
422 }
423
424
425 ///
426 /// 下载一个文件
427 ///
428 /// 要下载的文件名
429 /// 本地目录(不得以\结束)
430 /// 保存在本地时的文件名
431 public void Get(string strRemoteFileName, string strFolder, string strLocalFileName)
432 {
433 if (!bConnected)
434 {
435 Connect();
436 }
437 SetTransferType(TransferType.Binary);
438 if (strLocalFileName.Equals(""))
439 {
440 strLocalFileName = strRemoteFileName;
441 }
442 if (!File.Exists(strLocalFileName))
443 {
444 Stream st = File.Create(strLocalFileName);
445 st.Close();
446 }
447 FileStream output = new
448 FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create);
449 Socket socketData = CreateDataSocket();
450 SendCommand("RETR " + strRemoteFileName);
451 if (!(iReplyCode == 150 || iReplyCode == 125
452 || iReplyCode == 226 || iReplyCode == 250))
453 {
454 throw new IOException(strReply.Substring(4));
455 }
456 while (true)
457 {
458 int iBytes = socketData.Receive(buffer, buffer.Length, 0);
459 output.Write(buffer, 0, iBytes);
460 if (iBytes 0)
517 {
518 socketData.Send(buffer, iBytes, 0);
519 }
520 input.Close();
521 if (socketData.Connected)
522 {
523 socketData.Close();
524 }
525 if (!(iReplyCode == 226 || iReplyCode == 250))
526 {
527 ReadReply();
528 if (!(iReplyCode == 226 || iReplyCode == 250))
529 {
530 throw new IOException(strReply.Substring(4));
531 }
532 }
533 }
534
535 #endregion
536
537 #region 目录操作
538 ///
539 /// 创建目录
540 ///
541 /// 目录名
542 public void MkDir(string strDirName)
543 {
544 if (!bConnected)
545 {
546 Connect();
547 }
548 SendCommand("MKD " + strDirName);
549 if (iReplyCode != 257)
550 {
551 throw new IOException(strReply.Substring(4));
552 }
553 }
554
555
556 ///
557 /// 删除目录
558 ///
559 /// 目录名
560 public void RmDir(string strDirName)
561 {
562 if (!bConnected)
563 {
564 Connect();
565 }
566 SendCommand("RMD " + strDirName);
567 if (iReplyCode != 250)
568 {
569 throw new IOException(strReply.Substring(4));
570 }
571 }
572
573
574 ///
575 /// 改变目录
576 ///
577 /// 新的工作目录名
578 public void ChDir(string strDirName)
579 {
580 if (strDirName.Equals(".") || strDirName.Equals(""))
581 {
582 return;
583 }
584 if (!bConnected)
585 {
586 Connect();
587 }
588 SendCommand("CWD " + strDirName);
589 if (iReplyCode != 250)
590 {
591 throw new IOException(strReply.Substring(4));
592 }
593 strRemotePath = strDirName;
594 }
595
596 #endregion
597
598 #region 内部变量
599 ///
600 /// 服务器返回的应答信息(包含应答码)
601 ///
602 private string strMsg;
603 ///
604 /// 服务器返回的应答信息(包含应答码)
605 ///
606 private string strReply;
607 ///
608 /// 服务器返回的应答码
609 ///
610 private int iReplyCode;
611 ///
612 /// 进行控制连接的socket
613 ///
614 private Socket socketControl;
615 ///
616 /// 传输模式
617 ///
618 private TransferType trType;
619 ///
620 /// 接收和发送数据的缓冲区
621 ///
622 private static int BLOCK_SIZE = 512;
623 Byte[] buffer = new Byte[BLOCK_SIZE];
624 ///
625 /// 编码方式
626 ///
627 Encoding ASCII = Encoding.ASCII;
628 #endregion
629
630 #region 内部函数
631 ///
632 /// 将一行应答字符串记录在strReply和strMsg
633 /// 应答码记录在iReplyCode
634 ///
635 private void ReadReply()
636 {
637 strMsg = "";
638 strReply = ReadLine();
639 iReplyCode = Int32.Parse(strReply.Substring(0, 3));
640 }
641
642 ///
643 /// 建立进行数据连接的socket
644 ///
645 /// 数据连接socket
646 private Socket CreateDataSocket()
647 {
648 SendCommand("PASV");
649 if (iReplyCode != 227)
650 {
651 throw new IOException(strReply.Substring(4));
652 }
653 int index1 = strReply.IndexOf('(');
654 int index2 = strReply.IndexOf(')');
655 string ipData =
656 strReply.Substring(index1 + 1, index2 - index1 - 1);
657 int[] parts = new int[6];
658 int len = ipData.Length;
659 int partCount = 0;
660 string buf = "";
661 for (int i = 0; i < len && partCount |
|
|