准备陆续将二期项目的代码法上来,先来一个FTPClient类
FTPClient类
这个是根据网上的一个例子修改过来的
修正了中文编码存在的问题以及其他一些小的调整
下载
protected void DownLoad_Click(object sender, EventArgs e)

{
FTPClient ftpc = new FTPClient("127.0.0.1", @"\A2", "pcuser", "userpass", 21);
ftpc.Get("*.zip", @"C:");
}
修正了中文编码存在的问题以及其他一些小的调整
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Net.Sockets;
5
using System.Net;
6
using System.IO;
7
8
namespace WanFangData.Common
9

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

8
namespace WanFangData.Common9


{10
public class FTPClient11

{12

构造函数#region 构造函数13

14

/**//// <summary>15
/// 缺省构造函数16
/// </summary>17
public FTPClient()18

{19
strRemoteHost = "";20
strRemotePath = "";21
strRemoteUser = "";22
strRemotePass = "";23
strRemotePort = 21;24
bConnected = false;25
}26

27

/**//// <summary>28
/// 构造函数29
/// </summary>30
/// <param name="remoteHost"></param>31
/// <param name="remotePath"></param>32
/// <param name="remoteUser"></param>33
/// <param name="remotePass"></param>34
/// <param name="remotePort"></param>35
public FTPClient(string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort)36

{37
strRemoteHost = remoteHost;38
strRemotePath = remotePath;39
strRemoteUser = remoteUser;40
strRemotePass = remotePass;41
strRemotePort = remotePort;42
Connect();43
}44

45
#endregion46

47

登陆#region 登陆48

49

/**//// <summary>50
/// FTP服务器IP地址51
/// </summary>52
private string strRemoteHost;53
public string RemoteHost54

{55

get
{ return strRemoteHost; }56

set
{ strRemoteHost = value; }57
}58

59

/**//// <summary>60
/// FTP服务器端口61
/// </summary>62
private int strRemotePort;63
public int RemotePort64

{65

get
{ return strRemotePort; }66

set
{ strRemotePort = value; }67
}68

69

/**//// <summary>70
/// 当前服务器目录71
/// </summary>72
private string strRemotePath;73
public string RemotePath74

{75

get
{ return strRemotePath; }76

set
{ strRemotePath = value; }77
}78

79

/**//// <summary>80
/// 登录用户账号81
/// </summary>82
private string strRemoteUser;83
public string RemoteUser84

{85

set
{ strRemoteUser = value; }86
}87

88

/**//// <summary>89
/// 用户登录密码90
/// </summary>91
private string strRemotePass;92
public string RemotePass93

{94

set
{ strRemotePass = value; }95
}96

97

/**//// <summary>98
/// 是否登录99
/// </summary>100
private Boolean bConnected;101
public bool Connected102

{103

get
{ return bConnected; }104
}105

106
#endregion107

108

连接#region 连接109

110

/**//// <summary>111
/// 建立连接 112
/// </summary>113
public void Connect()114

{115
socketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);116
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), strRemotePort);117
// 连接118
try119

{120
socketControl.Connect(ep);121
}122
catch (Exception)123

{124
throw new IOException("不能连接到FTP服务器");125
}126
// 获取应答码127
ReadReply();128
if (iReplyCode != 220)129

{130
DisConnect();131
throw new IOException(strReply.Substring(4));132
}133
// 登陆134
SendCommand("USER " + strRemoteUser);135
if (!(iReplyCode == 331 || iReplyCode == 230))136

{137
CloseSocketConnect();//关闭连接138
throw new IOException(strReply.Substring(4));139
}140
if (iReplyCode != 230)141

{142
SendCommand("PASS " + strRemotePass);143
if (!(iReplyCode == 230 || iReplyCode == 202))144

{145
CloseSocketConnect();//关闭连接146
throw new IOException(strReply.Substring(4));147
}148
}149
bConnected = true; // 切换到目录150
ChDir(strRemotePath);151
}152

153

/**//// <summary>154
/// 关闭连接155
/// </summary>156
public void DisConnect()157

{158
if (socketControl != null)159

{160
SendCommand("QUIT");161
}162
CloseSocketConnect();163
}164

165
#endregion166

167

传输模式#region 传输模式168

169

/**//// <summary>170
/// 传输模式:二进制类型、ASCII类型171
/// </summary>172

public enum TransferType
{ Binary, ASCII };173

174

/**//// <summary>175
/// 设置传输模式176
/// </summary>177
/// <param name="ttType">传输模式</param>178
public void SetTransferType(TransferType ttType)179

{180
if (ttType == TransferType.Binary)181

{182
SendCommand("TYPE I");//binary类型传输183
}184
else185

{186
SendCommand("TYPE A");//ASCII类型传输187
}188
if (iReplyCode != 200)189

{190
throw new IOException(strReply.Substring(4));191
}192
else193

{194
trType = ttType;195
}196
}197

198

/**//// <summary>199
/// 获得传输模式200
/// </summary>201
/// <returns>传输模式</returns>202
public TransferType GetTransferType()203

{204
return trType;205
}206

207
#endregion208

209

文件操作#region 文件操作210

211

/**//// <summary>212
/// 获得文件列表213
/// </summary>214
/// <param name="strMask">文件名的匹配字符串</param>215
/// <returns></returns>216
public string[] Dir(string strMask)217

{218
// 建立链接219
if (!bConnected)220

{221
Connect();222
}223
//建立进行数据连接的socket224
Socket socketData = CreateDataSocket();225
//传送命令226
SendCommand("NLST " + strMask);227
//分析应答代码228
if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226))229

{230
throw new IOException(strReply.Substring(4));231
}232
//获得结果233
strMsg = "";234
while (true)235

{236
int iBytes = socketData.Receive(buffer, buffer.Length, 0);237
strMsg += Encoding.Default.GetString(buffer, 0, iBytes);238
if (iBytes < buffer.Length)239

{240
break;241
}242
}243

char[] seperator =
{ '\n' };244
string[] strsFileList = strMsg.Split(seperator, StringSplitOptions.RemoveEmptyEntries);245
socketData.Close();//数据socket关闭时也会有返回码246
if (iReplyCode != 226)247

{248
ReadReply();249
if (iReplyCode != 226)250

{251
throw new IOException(strReply.Substring(4));252
}253
}254
return strsFileList;255
}256

257

/**//// <summary>258
/// 获取文件大小259
/// </summary>260
/// <param name="strFileName">文件名</param>261
/// <returns>文件大小</returns>262
private long GetFileSize(string strFileName)263

{264
if (!bConnected)265

{266
Connect();267
}268
SendCommand("SIZE " + Path.GetFileName(strFileName));269
long lSize = 0;270
if (iReplyCode == 213)271

{272
lSize = Int64.Parse(strReply.Substring(4));273
}274
else275

{276
throw new IOException(strReply.Substring(4));277
}278
return lSize;279
}280

281

/**//// <summary>282
/// 删除283
/// </summary>284
/// <param name="strFileName">待删除文件名</param>285
public void Delete(string strFileName)286

{287
if (!bConnected)288

{289
Connect();290
}291
SendCommand("DELE " + strFileName);292
if (iReplyCode != 250)293

{294
throw new IOException(strReply.Substring(4));295
}296
}297

298

/**//// <summary>299
/// 重命名(如果新文件名与已有文件重名,将覆盖已有文件)300
/// </summary>301
/// <param name="strOldFileName">旧文件名</param>302
/// <param name="strNewFileName">新文件名</param>303
public void Rename(string strOldFileName, string strNewFileName)304

{305
if (!bConnected)306

{307
Connect();308
}309
SendCommand("RNFR " + strOldFileName);310
if (iReplyCode != 350)311

{312
throw new IOException(strReply.Substring(4));313
}314
// 如果新文件名与原有文件重名,将覆盖原有文件315
SendCommand("RNTO " + strNewFileName);316
if (iReplyCode != 250)317

{318
throw new IOException(strReply.Substring(4));319
}320
}321

322
#endregion323

324

上传和下载#region 上传和下载325

326

/**//// <summary>327
/// 下载一个文件328
/// </summary>329
/// <param name="strRemoteFileName">要下载的文件名</param>330
/// <param name="strFolder">本地目录(不得以\结束)</param>331
/// <param name="strLocalFileName">保存在本地时的文件名</param>332
public void Get(string strRemoteFileName, string strFolder, string strLocalFileName)333

{334
if (!bConnected)335

{336
Connect();337
}338
SetTransferType(TransferType.Binary);339
if (strLocalFileName.Equals(""))340

{341
strLocalFileName = strRemoteFileName;342
}343
FileStream output = new FileStream(strFolder + @"\" + strLocalFileName, FileMode.Create);344
Socket socketData = CreateDataSocket();345
SendCommand("RETR " + strRemoteFileName);346
if (!(iReplyCode == 150 || iReplyCode == 125347
|| iReplyCode == 226 || iReplyCode == 250))348

{349
throw new IOException(strReply.Substring(4));350
}351
while (true)352

{353
int iBytes = socketData.Receive(buffer, buffer.Length, 0);354
output.Write(buffer, 0, iBytes);355
if (iBytes <= 0)356

{357
break;358
}359
}360
output.Close();361
if (socketData.Connected)362

{363
socketData.Close();364
}365
if (!(iReplyCode == 226 || iReplyCode == 250))366

{367
ReadReply();368
if (!(iReplyCode == 226 || iReplyCode == 250))369

{370
throw new IOException(strReply.Substring(4));371
}372
}373
}374

375

/**//// <summary>376
/// 下载一批文件377
/// </summary>378
/// <param name="strFileNameMask">文件名的匹配字符串</param>379
/// <param name="strFolder">本地目录(不得以\结束)</param>380
public void Get(string strFileNameMask, string strFolder)381

{382
if (!bConnected)383

{384
Connect();385
}386
string[] strFiles = Dir(strFileNameMask);387
foreach (string strFile in strFiles)388

{389
if (!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是空字符串390

{391
Get(strFile.Trim(), strFolder, strFile.Trim());392
}393
}394
}395

396

397

/**//// <summary>398
/// 上传一个文件399
/// </summary>400
/// <param name="strFileName">本地文件名</param>401
public void Put(string strFileName)402

{403
if (!bConnected)404

{405
Connect();406
}407
Socket socketData = CreateDataSocket();408
SendCommand("STOR " + Path.GetFileName(strFileName));409
if (!(iReplyCode == 125 || iReplyCode == 150))410

{411
throw new IOException(strReply.Substring(4));412
}413
FileStream input = new414
FileStream(strFileName, FileMode.Open);415
int iBytes = 0;416
while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0)417

{418
socketData.Send(buffer, iBytes, 0);419
}420
input.Close();421
if (socketData.Connected)422

{423
socketData.Close();424
}425
if (!(iReplyCode == 226 || iReplyCode == 250))426

{427
ReadReply();428
if (!(iReplyCode == 226 || iReplyCode == 250))429

{430
throw new IOException(strReply.Substring(4));431
}432
}433
}434

435

/**//// <summary>436
/// 上传一批文件437
/// </summary>438
/// <param name="strFolder">本地目录(不得以\结束)</param>439
/// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param>440
public void Put(string strFolder, string strFileNameMask)441

{442
string[] strFiles = Directory.GetFiles(strFolder, strFileNameMask);443
foreach (string strFile in strFiles)444

{445
//strFile是完整的文件名(包含路径)446
Put(strFile);447
}448
}449

450
#endregion451

452

目录操作#region 目录操作453

454

/**//// <summary>455
/// 创建目录456
/// </summary>457
/// <param name="strDirName">目录名</param>458
public void MkDir(string strDirName)459

{460
if (!bConnected)461

{462
Connect();463
}464
SendCommand("MKD " + strDirName);465
if (iReplyCode != 257)466

{467
throw new IOException(strReply.Substring(4));468
}469
}470

471

/**//// <summary>472
/// 删除目录473
/// </summary>474
/// <param name="strDirName">目录名</param>475
public void RmDir(string strDirName)476

{477
if (!bConnected)478

{479
Connect();480
}481
SendCommand("RMD " + strDirName);482
if (iReplyCode != 250)483

{484
throw new IOException(strReply.Substring(4));485
}486
}487

488

/**//// <summary>489
/// 改变目录490
/// </summary>491
/// <param name="strDirName">新的工作目录名</param>492
public void ChDir(string strDirName)493

{494
if (strDirName.Equals(".") || strDirName.Equals(""))495

{496
return;497
}498
if (!bConnected)499

{500
Connect();501
}502
SendCommand("CWD " + strDirName);503
if (iReplyCode != 250)504

{505
throw new IOException(strReply.Substring(4));506
}507
this.strRemotePath = strDirName;508
}509

510
#endregion511

512

内部变量#region 内部变量513

514

/**//// <summary>515
/// 服务器返回的应答信息(包含应答码)516
/// </summary>517
private string strMsg;518

/**//// <summary>519
/// 服务器返回的应答信息(包含应答码)520
/// </summary>521
private string strReply;522

/**//// <summary>523
/// 服务器返回的应答码524
/// </summary>525
private int iReplyCode;526

/**//// <summary>527
/// 进行控制连接的socket528
/// </summary>529
private Socket socketControl;530

/**//// <summary>531
/// 传输模式532
/// </summary>533
private TransferType trType;534

/**//// <summary>535
/// 接收和发送数据的缓冲区536
/// </summary>537
private static int BLOCK_SIZE = 512;538
Byte[] buffer = new Byte[BLOCK_SIZE];539

540
#endregion541

542

内部函数#region 内部函数543

544

/**//// <summary>545
/// 将一行应答字符串记录在strReply和strMsg546
/// 应答码记录在iReplyCode547
/// </summary>548
private void ReadReply()549

{550
strMsg = "";551
strReply = ReadLine();552
iReplyCode = Int32.Parse(strReply.Substring(0, 3));553
}554

555

/**//// <summary>556
/// 建立进行数据连接的socket557
/// </summary>558
/// <returns>数据连接socket</returns>559
private Socket CreateDataSocket()560

{561
SendCommand("PASV");562
if (iReplyCode != 227)563

{564
throw new IOException(strReply.Substring(4));565
}566
int index1 = strReply.IndexOf('(');567
int index2 = strReply.IndexOf(')');568
string ipData =569
strReply.Substring(index1 + 1, index2 - index1 - 1);570
int[] parts = new int[6];571
int len = ipData.Length;572
int partCount = 0;573
string buf = "";574
for (int i = 0; i < len && partCount <= 6; i++)575

{576
char ch = Char.Parse(ipData.Substring(i, 1));577
if (Char.IsDigit(ch))578
buf += ch;579
else if (ch != ',')580

{581
throw new IOException("Malformed PASV strReply: " +582
strReply);583
}584
if (ch == ',' || i + 1 == len)585

{586
try587

{588
parts[partCount++] = Int32.Parse(buf);589
buf = "";590
}591
catch (Exception)592

{593
throw new IOException("Malformed PASV strReply: " +594
strReply);595
}596
}597
}598
string ipAddress = parts[0] + "." + parts[1] + "." +599
parts[2] + "." + parts[3];600
int port = (parts[4] << 8) + parts[5];601
Socket s = new602
Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);603
IPEndPoint ep = new604
IPEndPoint(IPAddress.Parse(ipAddress), port);605
try606

{607
s.Connect(ep);608
}609
catch (Exception)610

{611
throw new IOException("Can't connect to remote server");612
}613
return s;614
}615

616

/**//// <summary>617
/// 关闭socket连接(用于登录以前)618
/// </summary>619
private void CloseSocketConnect()620

{621
if (socketControl != null)622

{623
socketControl.Close();624
socketControl = null;625
}626
bConnected = false;627
}628

629

/**//// <summary>630
/// 读取Socket返回的所有字符串631
/// </summary>632
/// <returns>包含应答码的字符串行</returns>633
private string ReadLine()634

{635
while (true)636

{637
int iBytes = socketControl.Receive(buffer, buffer.Length, 0);638
strMsg += Encoding.Default.GetString(buffer, 0, iBytes);639
if (iBytes < buffer.Length)640

{641
break;642
}643
}644

char[] seperator =
{ '\n' };645
string[] mess = strMsg.Split(seperator);646
if (strMsg.Length > 2)647

{648
strMsg = mess[mess.Length - 2];649
//seperator[0]是10,换行符是由13和0组成的,分隔后10后面虽没有字符串,650
//但也会分配为空字符串给后面(也是最后一个)字符串数组,651
//所以最后一个mess是没用的空字符串652
//但为什么不直接取mess[0],因为只有最后一行字符串应答码与信息之间有空格653
}654
else655

{656
strMsg = mess[0];657
}658
if (!strMsg.Substring(3, 1).Equals(" "))//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串)659

{660
return ReadLine();661
}662
return strMsg;663
}664

665

/**//// <summary>666
/// 发送命令并获取应答码和最后一行应答字符串667
/// </summary>668
/// <param name="strCommand">命令</param>669
private void SendCommand(String strCommand)670

{671
Byte[] cmdBytes = Encoding.Default.GetBytes((strCommand + "\r\n").ToCharArray());672
socketControl.Send(cmdBytes, cmdBytes.Length, 0);673
ReadReply();674
}675

676
#endregion677
}678
}下载
protected void DownLoad_Click(object sender, EventArgs e)
{
FTPClient ftpc = new FTPClient("127.0.0.1", @"\A2", "pcuser", "userpass", 21);
ftpc.Get("*.zip", @"C:");
}
浙公网安备 33010602011771号