1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Net; 5 using System.IO; 6 using System.Globalization; 7 using System.Text.RegularExpressions; 8 9 namespace System.Net.Ftp 10 { 11 /// <summary> 12 /// FTP处理操作类 13 /// 功能: 14 /// 下载文件 15 /// 上传文件 16 /// 上传文件的进度信息 17 /// 下载文件的进度信息 18 /// 删除文件 19 /// 列出文件 20 /// 列出目录 21 /// 进入子目录 22 /// 退出当前目录返回上一层目录 23 /// 判断远程文件是否存在 24 /// 判断远程文件是否存在 25 /// 删除远程文件 26 /// 建立目录 27 /// 删除目录 28 /// 文件(目录)改名 29 30 /// </summary> 31 /// <remarks> 32 /// 创建人:南疯 33 /// 创建时间:2007年4月28日 34 /// </remarks> 35 #region 文件信息结构 36 public struct FileStruct 37 { 38 public string Flags; 39 public string Owner; 40 public string Group; 41 public bool IsDirectory; 42 public DateTime CreateTime; 43 public string Name; 44 } 45 public enum FileListStyle 46 { 47 UnixStyle, 48 WindowsStyle, 49 Unknown 50 } 51 #endregion 52 public class clsFTP 53 { 54 #region 属性信息 55 /// <summary> 56 /// FTP请求对象 57 /// </summary> 58 FtpWebRequest Request = null; 59 /// <summary> 60 /// FTP响应对象 61 /// </summary> 62 FtpWebResponse Response = null; 63 /// <summary> 64 /// FTP服务器地址 65 /// </summary> 66 private Uri _Uri; 67 /// <summary> 68 /// FTP服务器地址 69 /// </summary> 70 public Uri Uri 71 { 72 get 73 { 74 if (_DirectoryPath == "/") 75 { 76 return _Uri; 77 } 78 else 79 { 80 string strUri = _Uri.ToString(); 81 if (strUri.EndsWith("/")) 82 { 83 strUri = strUri.Substring(0, strUri.Length - 1); 84 } 85 return new Uri(strUri + this.DirectoryPath); 86 } 87 } 88 set 89 { 90 if (value.Scheme != Uri.UriSchemeFtp) 91 { 92 throw new Exception("Ftp 地址格式错误!"); 93 } 94 _Uri = new Uri(value.GetLeftPart(UriPartial.Authority)); 95 _DirectoryPath = value.AbsolutePath; 96 if (!_DirectoryPath.EndsWith("/")) 97 { 98 _DirectoryPath += "/"; 99 } 100 } 101 } 102 103 /// <summary> 104 /// 当前工作目录 105 /// </summary> 106 private string _DirectoryPath; 107 108 /// <summary> 109 /// 当前工作目录 110 /// </summary> 111 public string DirectoryPath 112 { 113 get { return _DirectoryPath; } 114 set { _DirectoryPath = value; } 115 } 116 117 /// <summary> 118 /// FTP登录用户 119 /// </summary> 120 private string _UserName; 121 /// <summary> 122 /// FTP登录用户 123 /// </summary> 124 public string UserName 125 { 126 get { return _UserName; } 127 set { _UserName = value; } 128 } 129 130 /// <summary> 131 /// 错误信息 132 /// </summary> 133 private string _ErrorMsg; 134 /// <summary> 135 /// 错误信息 136 /// </summary> 137 public string ErrorMsg 138 { 139 get { return _ErrorMsg; } 140 set { _ErrorMsg = value; } 141 } 142 143 /// <summary> 144 /// FTP登录密码 145 /// </summary> 146 private string _Password; 147 /// <summary> 148 /// FTP登录密码 149 /// </summary> 150 public string Password 151 { 152 get { return _Password; } 153 set { _Password = value; } 154 } 155 156 /// <summary> 157 /// 连接FTP服务器的代理服务 158 /// </summary> 159 private WebProxy _Proxy = null; 160 /// <summary> 161 /// 连接FTP服务器的代理服务 162 /// </summary> 163 public WebProxy Proxy 164 { 165 get 166 { 167 return _Proxy; 168 } 169 set 170 { 171 _Proxy = value; 172 } 173 } 174 175 /// <summary> 176 /// 是否需要删除临时文件 177 /// </summary> 178 private bool _isDeleteTempFile = false; 179 /// <summary> 180 /// 异步上传所临时生成的文件 181 /// </summary> 182 private string _UploadTempFile = ""; 183 #endregion 184 #region 事件 185 public delegate void De_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e); 186 public delegate void De_DownloadDataCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e); 187 public delegate void De_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e); 188 public delegate void De_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e); 189 190 /// <summary> 191 /// 异步下载进度发生改变触发的事件 192 /// </summary> 193 public event De_DownloadProgressChanged DownloadProgressChanged; 194 /// <summary> 195 /// 异步下载文件完成之后触发的事件 196 /// </summary> 197 public event De_DownloadDataCompleted DownloadDataCompleted; 198 /// <summary> 199 /// 异步上传进度发生改变触发的事件 200 /// </summary> 201 public event De_UploadProgressChanged UploadProgressChanged; 202 /// <summary> 203 /// 异步上传文件完成之后触发的事件 204 /// </summary> 205 public event De_UploadFileCompleted UploadFileCompleted; 206 #endregion 207 #region 构造析构函数 208 /// <summary> 209 /// 构造函数 210 /// </summary> 211 /// <param name="FtpUri">FTP地址</param> 212 /// <param name="strUserName">登录用户名</param> 213 /// <param name="strPassword">登录密码</param> 214 public clsFTP(Uri FtpUri, string strUserName, string strPassword) 215 { 216 this._Uri = new Uri(FtpUri.GetLeftPart(UriPartial.Authority)); 217 _DirectoryPath = FtpUri.AbsolutePath; 218 if (!_DirectoryPath.EndsWith("/")) 219 { 220 _DirectoryPath += "/"; 221 } 222 this._UserName = strUserName; 223 this._Password = strPassword; 224 this._Proxy = null; 225 } 226 /// <summary> 227 /// 构造函数 228 /// </summary> 229 /// <param name="FtpUri">FTP地址</param> 230 /// <param name="strUserName">登录用户名</param> 231 /// <param name="strPassword">登录密码</param> 232 /// <param name="objProxy">连接代理</param> 233 public clsFTP(Uri FtpUri, string strUserName, string strPassword, WebProxy objProxy) 234 { 235 this._Uri = new Uri(FtpUri.GetLeftPart(UriPartial.Authority)); 236 _DirectoryPath = FtpUri.AbsolutePath; 237 if (!_DirectoryPath.EndsWith("/")) 238 { 239 _DirectoryPath += "/"; 240 } 241 this._UserName = strUserName; 242 this._Password = strPassword; 243 this._Proxy = objProxy; 244 } 245 /// <summary> 246 /// 构造函数 247 /// </summary> 248 public clsFTP() 249 { 250 this._UserName = "anonymous"; //匿名用户 251 this._Password = "@anonymous"; 252 this._Uri = null; 253 this._Proxy = null; 254 } 255 256 /// <summary> 257 /// 析构函数 258 /// </summary> 259 ~clsFTP() 260 { 261 if (Response != null) 262 { 263 Response.Close(); 264 Response = null; 265 } 266 if (Request != null) 267 { 268 Request.Abort(); 269 Request = null; 270 } 271 } 272 #endregion 273 #region 建立连接 274 /// <summary> 275 /// 建立FTP链接,返回响应对象 276 /// </summary> 277 /// <param name="uri">FTP地址</param> 278 /// <param name="FtpMathod">操作命令</param> 279 private FtpWebResponse Open(Uri uri, string FtpMathod) 280 { 281 try 282 { 283 Request = (FtpWebRequest) WebRequest.Create(uri); 284 Request.Method = FtpMathod; 285 Request.UseBinary = true; 286 Request.Credentials = new NetworkCredential(this.UserName, this.Password); 287 if (this.Proxy != null) 288 { 289 Request.Proxy = this.Proxy; 290 } 291 return (FtpWebResponse) Request.GetResponse(); 292 } 293 catch (Exception ep) 294 { 295 ErrorMsg = ep.ToString(); 296 throw ep; 297 } 298 } 299 /// <summary> 300 /// 建立FTP链接,返回请求对象 301 /// </summary> 302 /// <param name="uri">FTP地址</param> 303 /// <param name="FtpMathod">操作命令</param> 304 private FtpWebRequest OpenRequest(Uri uri, string FtpMathod) 305 { 306 try 307 { 308 Request = (FtpWebRequest) WebRequest.Create(uri); 309 Request.Method = FtpMathod; 310 Request.UseBinary = true; 311 Request.Credentials = new NetworkCredential(this.UserName, this.Password); 312 if (this.Proxy != null) 313 { 314 Request.Proxy = this.Proxy; 315 } 316 return Request; 317 } 318 catch (Exception ep) 319 { 320 ErrorMsg = ep.ToString(); 321 throw ep; 322 } 323 } 324 #endregion 325 #region 下载文件 326 327 /// <summary> 328 /// 从FTP服务器下载文件,使用与远程文件同名的文件名来保存文件 329 /// </summary> 330 /// <param name="RemoteFileName">远程文件名</param> 331 /// <param name="LocalPath">本地路径</param> 332 333 public bool DownloadFile(string RemoteFileName, string LocalPath) 334 { 335 return DownloadFile(RemoteFileName, LocalPath, RemoteFileName); 336 } 337 /// <summary> 338 /// 从FTP服务器下载文件,指定本地路径和本地文件名 339 /// </summary> 340 /// <param name="RemoteFileName">远程文件名</param> 341 /// <param name="LocalPath">本地路径</param> 342 /// <param name="LocalFilePath">保存文件的本地路径,后面带有""</param> 343 /// <param name="LocalFileName">保存本地的文件名</param> 344 public bool DownloadFile(string RemoteFileName, string LocalPath, string LocalFileName) 345 { 346 byte[] bt = null; 347 try 348 { 349 if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(LocalFileName) || !IsValidPathChars(LocalPath)) 350 { 351 throw new Exception("非法文件名或目录名!"); 352 } 353 if (!Directory.Exists(LocalPath)) 354 { 355 throw new Exception("本地文件路径不存在!"); 356 } 357 358 string LocalFullPath = Path.Combine(LocalPath, LocalFileName); 359 if (File.Exists(LocalFullPath)) 360 { 361 throw new Exception("当前路径下已经存在同名文件!"); 362 } 363 bt = DownloadFile(RemoteFileName); 364 if (bt != null) 365 { 366 FileStream stream = new FileStream(LocalFullPath, FileMode.Create); 367 stream.Write(bt, 0, bt.Length); 368 stream.Flush(); 369 stream.Close(); 370 return true; 371 } 372 else 373 { 374 return false; 375 } 376 } 377 catch (Exception ep) 378 { 379 ErrorMsg = ep.ToString(); 380 throw ep; 381 } 382 } 383 384 /// <summary> 385 /// 从FTP服务器下载文件,返回文件二进制数据 386 /// </summary> 387 /// <param name="RemoteFileName">远程文件名</param> 388 public byte[] DownloadFile(string RemoteFileName) 389 { 390 try 391 { 392 if (!IsValidFileChars(RemoteFileName)) 393 { 394 throw new Exception("非法文件名或目录名!"); 395 } 396 Response = Open(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.DownloadFile); 397 Stream Reader = Response.GetResponseStream(); 398 399 MemoryStream mem = new MemoryStream(1024 * 500); 400 byte[] buffer = new byte[1024]; 401 int bytesRead = 0; 402 int TotalByteRead = 0; 403 while (true) 404 { 405 bytesRead = Reader.Read(buffer, 0, buffer.Length); 406 TotalByteRead += bytesRead; 407 if (bytesRead == 0) 408 break; 409 mem.Write(buffer, 0, bytesRead); 410 } 411 if (mem.Length > 0) 412 { 413 return mem.ToArray(); 414 } 415 else 416 { 417 return null; 418 } 419 } 420 catch (Exception ep) 421 { 422 ErrorMsg = ep.ToString(); 423 throw ep; 424 } 425 } 426 #endregion 427 #region 异步下载文件 428 /// <summary> 429 /// 从FTP服务器异步下载文件,指定本地路径和本地文件名 430 /// </summary> 431 /// <param name="RemoteFileName">远程文件名</param> 432 /// <param name="LocalPath">保存文件的本地路径,后面带有""</param> 433 /// <param name="LocalFileName">保存本地的文件名</param> 434 public void DownloadFileAsync(string RemoteFileName, string LocalPath, string LocalFileName) 435 { 436 byte[] bt = null; 437 try 438 { 439 if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(LocalFileName) || !IsValidPathChars(LocalPath)) 440 { 441 throw new Exception("非法文件名或目录名!"); 442 } 443 if (!Directory.Exists(LocalPath)) 444 { 445 throw new Exception("本地文件路径不存在!"); 446 } 447 448 string LocalFullPath = Path.Combine(LocalPath, LocalFileName); 449 if (File.Exists(LocalFullPath)) 450 { 451 throw new Exception("当前路径下已经存在同名文件!"); 452 } 453 DownloadFileAsync(RemoteFileName, LocalFullPath); 454 455 } 456 catch (Exception ep) 457 { 458 ErrorMsg = ep.ToString(); 459 throw ep; 460 } 461 } 462 463 /// <summary> 464 /// 从FTP服务器异步下载文件,指定本地完整路径文件名 465 /// </summary> 466 /// <param name="RemoteFileName">远程文件名</param> 467 /// <param name="LocalFullPath">本地完整路径文件名</param> 468 public void DownloadFileAsync(string RemoteFileName, string LocalFullPath) 469 { 470 try 471 { 472 if (!IsValidFileChars(RemoteFileName)) 473 { 474 throw new Exception("非法文件名或目录名!"); 475 } 476 if (File.Exists(LocalFullPath)) 477 { 478 throw new Exception("当前路径下已经存在同名文件!"); 479 } 480 MyWebClient client = new MyWebClient(); 481 482 client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged); 483 client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(client_DownloadFileCompleted); 484 client.Credentials = new NetworkCredential(this.UserName, this.Password); 485 if (this.Proxy != null) 486 { 487 client.Proxy = this.Proxy; 488 } 489 client.DownloadFileAsync(new Uri(this.Uri.ToString() + RemoteFileName), LocalFullPath); 490 } 491 catch (Exception ep) 492 { 493 ErrorMsg = ep.ToString(); 494 throw ep; 495 } 496 } 497 498 /// <summary> 499 /// 异步下载文件完成之后触发的事件 500 /// </summary> 501 /// <param name="sender">下载对象</param> 502 /// <param name="e">数据信息对象</param> 503 void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) 504 { 505 if (DownloadDataCompleted != null) 506 { 507 DownloadDataCompleted(sender, e); 508 } 509 } 510 511 /// <summary> 512 /// 异步下载进度发生改变触发的事件 513 /// </summary> 514 /// <param name="sender">下载对象</param> 515 /// <param name="e">进度信息对象</param> 516 void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) 517 { 518 if (DownloadProgressChanged != null) 519 { 520 DownloadProgressChanged(sender, e); 521 } 522 } 523 #endregion 524 #region 上传文件 525 /// <summary> 526 /// 上传文件到FTP服务器 527 /// </summary> 528 /// <param name="LocalFullPath">本地带有完整路径的文件名</param> 529 public bool UploadFile(string LocalFullPath) 530 { 531 return UploadFile(LocalFullPath, Path.GetFileName(LocalFullPath), false); 532 } 533 /// <summary> 534 /// 上传文件到FTP服务器 535 /// </summary> 536 /// <param name="LocalFullPath">本地带有完整路径的文件</param> 537 /// <param name="OverWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param> 538 public bool UploadFile(string LocalFullPath, bool OverWriteRemoteFile) 539 { 540 return UploadFile(LocalFullPath, Path.GetFileName(LocalFullPath), OverWriteRemoteFile); 541 } 542 /// <summary> 543 /// 上传文件到FTP服务器 544 /// </summary> 545 /// <param name="LocalFullPath">本地带有完整路径的文件</param> 546 /// <param name="RemoteFileName">要在FTP服务器上面保存文件名</param> 547 public bool UploadFile(string LocalFullPath, string RemoteFileName) 548 { 549 return UploadFile(LocalFullPath, RemoteFileName, false); 550 } 551 /// <summary> 552 /// 上传文件到FTP服务器 553 /// </summary> 554 /// <param name="LocalFullPath">本地带有完整路径的文件名</param> 555 /// <param name="RemoteFileName">要在FTP服务器上面保存文件名</param> 556 /// <param name="OverWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param> 557 public bool UploadFile(string LocalFullPath, string RemoteFileName, bool OverWriteRemoteFile) 558 { 559 try 560 { 561 if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(Path.GetFileName(LocalFullPath)) || !IsValidPathChars(Path.GetDirectoryName(LocalFullPath))) 562 { 563 throw new Exception("非法文件名或目录名!"); 564 } 565 if (File.Exists(LocalFullPath)) 566 { 567 FileStream Stream = new FileStream(LocalFullPath, FileMode.Open, FileAccess.Read); 568 byte[] bt = new byte[Stream.Length]; 569 Stream.Read(bt, 0, (Int32) Stream.Length); //注意,因为Int32的最大限制,最大上传文件只能是大约2G多一点 570 Stream.Close(); 571 return UploadFile(bt, RemoteFileName, OverWriteRemoteFile); 572 } 573 else 574 { 575 throw new Exception("本地文件不存在!"); 576 } 577 } 578 catch (Exception ep) 579 { 580 ErrorMsg = ep.ToString(); 581 throw ep; 582 } 583 } 584 /// <summary> 585 /// 上传文件到FTP服务器 586 /// </summary> 587 /// <param name="FileBytes">上传的二进制数据</param> 588 /// <param name="RemoteFileName">要在FTP服务器上面保存文件名</param> 589 public bool UploadFile(byte[] FileBytes, string RemoteFileName) 590 { 591 if (!IsValidFileChars(RemoteFileName)) 592 { 593 throw new Exception("非法文件名或目录名!"); 594 } 595 return UploadFile(FileBytes, RemoteFileName, false); 596 } 597 /// <summary> 598 /// 上传文件到FTP服务器 599 /// </summary> 600 /// <param name="FileBytes">文件二进制内容</param> 601 /// <param name="RemoteFileName">要在FTP服务器上面保存文件名</param> 602 /// <param name="OverWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param> 603 public bool UploadFile(byte[] FileBytes, string RemoteFileName, bool OverWriteRemoteFile) 604 { 605 try 606 { 607 if (!IsValidFileChars(RemoteFileName)) 608 { 609 throw new Exception("非法文件名!"); 610 } 611 if (!OverWriteRemoteFile && FileExist(RemoteFileName)) 612 { 613 throw new Exception("FTP服务上面已经存在同名文件!"); 614 } 615 Response = Open(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.UploadFile); 616 Stream requestStream = Request.GetRequestStream(); 617 MemoryStream mem = new MemoryStream(FileBytes); 618 619 byte[] buffer = new byte[1024]; 620 int bytesRead = 0; 621 int TotalRead = 0; 622 while (true) 623 { 624 bytesRead = mem.Read(buffer, 0, buffer.Length); 625 if (bytesRead == 0) 626 break; 627 TotalRead += bytesRead; 628 requestStream.Write(buffer, 0, bytesRead); 629 } 630 requestStream.Close(); 631 Response = (FtpWebResponse) Request.GetResponse(); 632 mem.Close(); 633 mem.Dispose(); 634 FileBytes = null; 635 return true; 636 } 637 catch (Exception ep) 638 { 639 ErrorMsg = ep.ToString(); 640 throw ep; 641 } 642 } 643 #endregion 644 #region 异步上传文件 645 /// <summary> 646 /// 异步上传文件到FTP服务器 647 /// </summary> 648 /// <param name="LocalFullPath">本地带有完整路径的文件名</param> 649 public void UploadFileAsync(string LocalFullPath) 650 { 651 UploadFileAsync(LocalFullPath, Path.GetFileName(LocalFullPath), false); 652 } 653 /// <summary> 654 /// 异步上传文件到FTP服务器 655 /// </summary> 656 /// <param name="LocalFullPath">本地带有完整路径的文件</param> 657 /// <param name="OverWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param> 658 public void UploadFileAsync(string LocalFullPath, bool OverWriteRemoteFile) 659 { 660 UploadFileAsync(LocalFullPath, Path.GetFileName(LocalFullPath), OverWriteRemoteFile); 661 } 662 /// <summary> 663 /// 异步上传文件到FTP服务器 664 /// </summary> 665 /// <param name="LocalFullPath">本地带有完整路径的文件</param> 666 /// <param name="RemoteFileName">要在FTP服务器上面保存文件名</param> 667 public void UploadFileAsync(string LocalFullPath, string RemoteFileName) 668 { 669 UploadFileAsync(LocalFullPath, RemoteFileName, false); 670 } 671 /// <summary> 672 /// 异步上传文件到FTP服务器 673 /// </summary> 674 /// <param name="LocalFullPath">本地带有完整路径的文件名</param> 675 /// <param name="RemoteFileName">要在FTP服务器上面保存文件名</param> 676 /// <param name="OverWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param> 677 public void UploadFileAsync(string LocalFullPath, string RemoteFileName, bool OverWriteRemoteFile) 678 { 679 try 680 { 681 if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(Path.GetFileName(LocalFullPath)) || !IsValidPathChars(Path.GetDirectoryName(LocalFullPath))) 682 { 683 throw new Exception("非法文件名或目录名!"); 684 } 685 if (!OverWriteRemoteFile && FileExist(RemoteFileName)) 686 { 687 throw new Exception("FTP服务上面已经存在同名文件!"); 688 } 689 if (File.Exists(LocalFullPath)) 690 { 691 MyWebClient client = new MyWebClient(); 692 693 client.UploadProgressChanged += new UploadProgressChangedEventHandler(client_UploadProgressChanged); 694 client.UploadFileCompleted += new UploadFileCompletedEventHandler(client_UploadFileCompleted); 695 client.Credentials = new NetworkCredential(this.UserName, this.Password); 696 if (this.Proxy != null) 697 { 698 client.Proxy = this.Proxy; 699 } 700 client.UploadFileAsync(new Uri(this.Uri.ToString() + RemoteFileName), LocalFullPath); 701 702 } 703 else 704 { 705 throw new Exception("本地文件不存在!"); 706 } 707 } 708 catch (Exception ep) 709 { 710 ErrorMsg = ep.ToString(); 711 throw ep; 712 } 713 } 714 /// <summary> 715 /// 异步上传文件到FTP服务器 716 /// </summary> 717 /// <param name="FileBytes">上传的二进制数据</param> 718 /// <param name="RemoteFileName">要在FTP服务器上面保存文件名</param> 719 public void UploadFileAsync(byte[] FileBytes, string RemoteFileName) 720 { 721 if (!IsValidFileChars(RemoteFileName)) 722 { 723 throw new Exception("非法文件名或目录名!"); 724 } 725 UploadFileAsync(FileBytes, RemoteFileName, false); 726 } 727 /// <summary> 728 /// 异步上传文件到FTP服务器 729 /// </summary> 730 /// <param name="FileBytes">文件二进制内容</param> 731 /// <param name="RemoteFileName">要在FTP服务器上面保存文件名</param> 732 /// <param name="OverWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param> 733 public void UploadFileAsync(byte[] FileBytes, string RemoteFileName, bool OverWriteRemoteFile) 734 { 735 try 736 { 737 738 if (!IsValidFileChars(RemoteFileName)) 739 { 740 throw new Exception("非法文件名!"); 741 } 742 if (!OverWriteRemoteFile && FileExist(RemoteFileName)) 743 { 744 throw new Exception("FTP服务上面已经存在同名文件!"); 745 } 746 string TempPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Templates); 747 if (!TempPath.EndsWith("\")) 748 { 749 TempPath += "\"; 750 } 751 string TempFile = TempPath + Path.GetRandomFileName(); 752 TempFile = Path.ChangeExtension(TempFile, Path.GetExtension(RemoteFileName)); 753 FileStream Stream = new FileStream(TempFile, FileMode.CreateNew, FileAccess.Write); 754 Stream.Write(FileBytes, 0, FileBytes.Length); //注意,因为Int32的最大限制,最大上传文件只能是大约2G多一点 755 Stream.Flush(); 756 Stream.Close(); 757 Stream.Dispose(); 758 _isDeleteTempFile = true; 759 _UploadTempFile = TempFile; 760 FileBytes = null; 761 UploadFileAsync(TempFile, RemoteFileName, OverWriteRemoteFile); 762 763 764 765 } 766 catch (Exception ep) 767 { 768 ErrorMsg = ep.ToString(); 769 throw ep; 770 } 771 } 772 773 /// <summary> 774 /// 异步上传文件完成之后触发的事件 775 /// </summary> 776 /// <param name="sender">下载对象</param> 777 /// <param name="e">数据信息对象</param> 778 void client_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e) 779 { 780 if (_isDeleteTempFile) 781 { 782 if (File.Exists(_UploadTempFile)) 783 { 784 File.SetAttributes(_UploadTempFile, FileAttributes.Normal); 785 File.Delete(_UploadTempFile); 786 } 787 _isDeleteTempFile = false; 788 } 789 if (UploadFileCompleted != null) 790 { 791 UploadFileCompleted(sender, e); 792 } 793 } 794 795 /// <summary> 796 /// 异步上传进度发生改变触发的事件 797 /// </summary> 798 /// <param name="sender">下载对象</param> 799 /// <param name="e">进度信息对象</param> 800 void client_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e) 801 { 802 if (UploadProgressChanged != null) 803 { 804 UploadProgressChanged(sender, e); 805 } 806 } 807 #endregion 808 #region 列出目录文件信息 809 /// <summary> 810 /// 列出FTP服务器上面当前目录的所有文件和目录 811 /// </summary> 812 public FileStruct[] ListFilesAndDirectories() 813 { 814 Response = Open(this.Uri, WebRequestMethods.Ftp.ListDirectoryDetails); 815 StreamReader stream = new StreamReader(Response.GetResponseStream(), Encoding.Default); 816 string Datastring = stream.ReadToEnd(); 817 FileStruct[] list = GetList(Datastring); 818 return list; 819 } 820 /// <summary> 821 /// 列出FTP服务器上面当前目录的所有文件 822 /// </summary> 823 public FileStruct[] ListFiles() 824 { 825 FileStruct[] listAll = ListFilesAndDirectories(); 826 List<FileStruct> listFile = new List<FileStruct>(); 827 foreach (FileStruct file in listAll) 828 { 829 if (!file.IsDirectory) 830 { 831 listFile.Add(file); 832 } 833 } 834 return listFile.ToArray(); 835 } 836 837 /// <summary> 838 /// 列出FTP服务器上面当前目录的所有的目录 839 /// </summary> 840 public FileStruct[] ListDirectories() 841 { 842 FileStruct[] listAll = ListFilesAndDirectories(); 843 List<FileStruct> listDirectory = new List<FileStruct>(); 844 foreach (FileStruct file in listAll) 845 { 846 if (file.IsDirectory) 847 { 848 listDirectory.Add(file); 849 } 850 } 851 return listDirectory.ToArray(); 852 } 853 /// <summary> 854 /// 获得文件和目录列表 855 /// </summary> 856 /// <param name="datastring">FTP返回的列表字符信息</param> 857 private FileStruct[] GetList(string datastring) 858 { 859 List<FileStruct> myListArray = new List<FileStruct>(); 860 string[] dataRecords = datastring.Split(' '); 861 FileListStyle _directoryListStyle = GuessFileListStyle(dataRecords); 862 foreach (string s in dataRecords) 863 { 864 if (_directoryListStyle != FileListStyle.Unknown && s != "") 865 { 866 FileStruct f = new FileStruct(); 867 f.Name = ".."; 868 switch (_directoryListStyle) 869 { 870 case FileListStyle.UnixStyle: 871 f = ParseFileStructFromUnixStyleRecord(s); 872 break; 873 case FileListStyle.WindowsStyle: 874 f = ParseFileStructFromWindowsStyleRecord(s); 875 break; 876 } 877 if (!(f.Name == "." || f.Name == "..")) 878 { 879 myListArray.Add(f); 880 } 881 } 882 } 883 return myListArray.ToArray(); 884 } 885 886 /// <summary> 887 /// 从Windows格式中返回文件信息 888 /// </summary> 889 /// <param name="Record">文件信息</param> 890 private FileStruct ParseFileStructFromWindowsStyleRecord(string Record) 891 { 892 FileStruct f = new FileStruct(); 893 string processstr = Record.Trim(); 894 string dateStr = processstr.Substring(0, 8); 895 processstr = (processstr.Substring(8, processstr.Length - 8)).Trim(); 896 string timeStr = processstr.Substring(0, 7); 897 processstr = (processstr.Substring(7, processstr.Length - 7)).Trim(); 898 DateTimeFormatInfo myDTFI = new CultureInfo("en-US", false).DateTimeFormat; 899 myDTFI.ShortTimePattern = "t"; 900 f.CreateTime = DateTime.Parse(dateStr + " " + timeStr, myDTFI); 901 if (processstr.Substring(0, 5) == "<DIR>") 902 { 903 f.IsDirectory = true; 904 processstr = (processstr.Substring(5, processstr.Length - 5)).Trim(); 905 } 906 else 907 { 908 string[] strs = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // true); 909 processstr = strs[1]; 910 f.IsDirectory = false; 911 } 912 f.Name = processstr; 913 return f; 914 } 915 916 917 /// <summary> 918 /// 判断文件列表的方式Window方式还是Unix方式 919 /// </summary> 920 /// <param name="recordList">文件信息列表</param> 921 private FileListStyle GuessFileListStyle(string[] recordList) 922 { 923 foreach (string s in recordList) 924 { 925 if (s.Length > 10 926 && Regex.IsMatch(s.Substring(0, 10), "(-|d)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)")) 927 { 928 return FileListStyle.UnixStyle; 929 } 930 else if (s.Length > 8 931 && Regex.IsMatch(s.Substring(0, 8), "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]")) 932 { 933 return FileListStyle.WindowsStyle; 934 } 935 } 936 return FileListStyle.Unknown; 937 } 938 939 /// <summary> 940 /// 从Unix格式中返回文件信息 941 /// </summary> 942 /// <param name="Record">文件信息</param> 943 private FileStruct ParseFileStructFromUnixStyleRecord(string Record) 944 { 945 FileStruct f = new FileStruct(); 946 string processstr = Record.Trim(); 947 f.Flags = processstr.Substring(0, 10); 948 f.IsDirectory = (f.Flags[0] == 'd'); 949 processstr = (processstr.Substring(11)).Trim(); 950 _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); //跳过一部分 951 f.Owner = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); 952 f.Group = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); 953 _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); //跳过一部分 954 string yearOrTime = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[2]; 955 if (yearOrTime.IndexOf(":") >= 0) //time 956 { 957 processstr = processstr.Replace(yearOrTime, DateTime.Now.Year.ToString()); 958 } 959 f.CreateTime = DateTime.Parse(_cutSubstringFromStringWithTrim(ref processstr, ' ', 8)); 960 f.Name = processstr; //最后就是名称 961 return f; 962 } 963 964 /// <summary> 965 /// 按照一定的规则进行字符串截取 966 /// </summary> 967 /// <param name="s">截取的字符串</param> 968 /// <param name="c">查找的字符</param> 969 /// <param name="startIndex">查找的位置</param> 970 private string _cutSubstringFromStringWithTrim(ref string s, char c, int startIndex) 971 { 972 int pos1 = s.IndexOf(c, startIndex); 973 string retString = s.Substring(0, pos1); 974 s = (s.Substring(pos1)).Trim(); 975 return retString; 976 } 977 #endregion 978 #region 目录或文件存在的判断 979 /// <summary> 980 /// 判断当前目录下指定的子目录是否存在 981 /// </summary> 982 /// <param name="RemoteDirectoryName">指定的目录名</param> 983 public bool DirectoryExist(string RemoteDirectoryName) 984 { 985 try 986 { 987 if (!IsValidPathChars(RemoteDirectoryName)) 988 { 989 throw new Exception("目录名非法!"); 990 } 991 FileStruct[] listDir = ListDirectories(); 992 foreach (FileStruct dir in listDir) 993 { 994 if (dir.Name == RemoteDirectoryName) 995 { 996 return true; 997 } 998 } 999 return false; 1000 } 1001 catch (Exception ep) 1002 { 1003 ErrorMsg = ep.ToString(); 1004 throw ep; 1005 } 1006 } 1007 /// <summary> 1008 /// 判断一个远程文件是否存在服务器当前目录下面 1009 /// </summary> 1010 /// <param name="RemoteFileName">远程文件名</param> 1011 public bool FileExist(string RemoteFileName) 1012 { 1013 try 1014 { 1015 if (!IsValidFileChars(RemoteFileName)) 1016 { 1017 throw new Exception("文件名非法!"); 1018 } 1019 FileStruct[] listFile = ListFiles(); 1020 foreach (FileStruct file in listFile) 1021 { 1022 if (file.Name == RemoteFileName) 1023 { 1024 return true; 1025 } 1026 } 1027 return false; 1028 } 1029 catch (Exception ep) 1030 { 1031 ErrorMsg = ep.ToString(); 1032 throw ep; 1033 } 1034 } 1035 #endregion 1036 #region 删除文件 1037 /// <summary> 1038 /// 从FTP服务器上面删除一个文件 1039 /// </summary> 1040 /// <param name="RemoteFileName">远程文件名</param> 1041 public void DeleteFile(string RemoteFileName) 1042 { 1043 try 1044 { 1045 if (!IsValidFileChars(RemoteFileName)) 1046 { 1047 throw new Exception("文件名非法!"); 1048 } 1049 Response = Open(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.DeleteFile); 1050 } 1051 catch (Exception ep) 1052 { 1053 ErrorMsg = ep.ToString(); 1054 throw ep; 1055 } 1056 } 1057 #endregion 1058 #region 重命名文件 1059 /// <summary> 1060 /// 更改一个文件的名称或一个目录的名称 1061 /// </summary> 1062 /// <param name="RemoteFileName">原始文件或目录名称</param> 1063 /// <param name="NewFileName">新的文件或目录的名称</param> 1064 public bool ReName(string RemoteFileName, string NewFileName) 1065 { 1066 try 1067 { 1068 if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(NewFileName)) 1069 { 1070 throw new Exception("文件名非法!"); 1071 } 1072 if (RemoteFileName == NewFileName) 1073 { 1074 return true; 1075 } 1076 if (FileExist(RemoteFileName)) 1077 { 1078 Request = OpenRequest(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.Rename); 1079 Request.RenameTo = NewFileName; 1080 Response = (FtpWebResponse) Request.GetResponse(); 1081 1082 } 1083 else 1084 { 1085 throw new Exception("文件在服务器上不存在!"); 1086 } 1087 return true; 1088 } 1089 catch (Exception ep) 1090 { 1091 ErrorMsg = ep.ToString(); 1092 throw ep; 1093 } 1094 } 1095 #endregion 1096 #region 拷贝、移动文件 1097 /// <summary> 1098 /// 把当前目录下面的一个文件拷贝到服务器上面另外的目录中,注意,拷贝文件之后,当前工作目录还是文件原来所在的目录 1099 /// </summary> 1100 /// <param name="RemoteFile">当前目录下的文件名</param> 1101 /// <param name="DirectoryName">新目录名称。 1102 /// 说明:如果新目录是当前目录的子目录,则直接指定子目录。如: SubDirectory1/SubDirectory2 ; 1103 /// 如果新目录不是当前目录的子目录,则必须从根目录一级一级的指定。如: ./NewDirectory/SubDirectory1/SubDirectory2 1104 /// </param> 1105 /// <returns></returns> 1106 public bool CopyFileToAnotherDirectory(string RemoteFile, string DirectoryName) 1107 { 1108 string CurrentWorkDir = this.DirectoryPath; 1109 try 1110 { 1111 byte[] bt = DownloadFile(RemoteFile); 1112 GotoDirectory(DirectoryName); 1113 bool Success = UploadFile(bt, RemoteFile, false); 1114 this.DirectoryPath = CurrentWorkDir; 1115 return Success; 1116 } 1117 catch (Exception ep) 1118 { 1119 this.DirectoryPath = CurrentWorkDir; 1120 ErrorMsg = ep.ToString(); 1121 throw ep; 1122 } 1123 } 1124 /// <summary> 1125 /// 把当前目录下面的一个文件移动到服务器上面另外的目录中,注意,移动文件之后,当前工作目录还是文件原来所在的目录 1126 /// </summary> 1127 /// <param name="RemoteFile">当前目录下的文件名</param> 1128 /// <param name="DirectoryName">新目录名称。 1129 /// 说明:如果新目录是当前目录的子目录,则直接指定子目录。如: SubDirectory1/SubDirectory2 ; 1130 /// 如果新目录不是当前目录的子目录,则必须从根目录一级一级的指定。如: ./NewDirectory/SubDirectory1/SubDirectory2 1131 /// </param> 1132 /// <returns></returns> 1133 public bool MoveFileToAnotherDirectory(string RemoteFile, string DirectoryName) 1134 { 1135 string CurrentWorkDir = this.DirectoryPath; 1136 try 1137 { 1138 if (DirectoryName == "") 1139 return false; 1140 if (!DirectoryName.StartsWith("/")) 1141 DirectoryName = "/" + DirectoryName; 1142 if (!DirectoryName.EndsWith("/")) 1143 DirectoryName += "/"; 1144 bool Success = ReName(RemoteFile, DirectoryName + RemoteFile); 1145 this.DirectoryPath = CurrentWorkDir; 1146 return Success; 1147 } 1148 catch (Exception ep) 1149 { 1150 this.DirectoryPath = CurrentWorkDir; 1151 ErrorMsg = ep.ToString(); 1152 throw ep; 1153 } 1154 } 1155 #endregion 1156 #region 建立、删除子目录 1157 /// <summary> 1158 /// 在FTP服务器上当前工作目录建立一个子目录 1159 /// </summary> 1160 /// <param name="DirectoryName">子目录名称</param> 1161 public bool MakeDirectory(string DirectoryName) 1162 { 1163 try 1164 { 1165 if (!IsValidPathChars(DirectoryName)) 1166 { 1167 throw new Exception("目录名非法!"); 1168 } 1169 if (DirectoryExist(DirectoryName)) 1170 { 1171 throw new Exception("服务器上面已经存在同名的文件名或目录名!"); 1172 } 1173 Response = Open(new Uri(this.Uri.ToString() + DirectoryName), WebRequestMethods.Ftp.MakeDirectory); 1174 return true; 1175 } 1176 catch (Exception ep) 1177 { 1178 ErrorMsg = ep.ToString(); 1179 throw ep; 1180 } 1181 } 1182 /// <summary> 1183 /// 从当前工作目录中删除一个子目录 1184 /// </summary> 1185 /// <param name="DirectoryName">子目录名称</param> 1186 public bool RemoveDirectory(string DirectoryName) 1187 { 1188 try 1189 { 1190 if (!IsValidPathChars(DirectoryName)) 1191 { 1192 throw new Exception("目录名非法!"); 1193 } 1194 if (!DirectoryExist(DirectoryName)) 1195 { 1196 throw new Exception("服务器上面不存在指定的文件名或目录名!"); 1197 } 1198 Response = Open(new Uri(this.Uri.ToString() + DirectoryName), WebRequestMethods.Ftp.RemoveDirectory); 1199 return true; 1200 } 1201 catch (Exception ep) 1202 { 1203 ErrorMsg = ep.ToString(); 1204 throw ep; 1205 } 1206 } 1207 #endregion 1208 #region 文件、目录名称有效性判断 1209 /// <summary> 1210 /// 判断目录名中字符是否合法 1211 /// </summary> 1212 /// <param name="DirectoryName">目录名称</param> 1213 public bool IsValidPathChars(string DirectoryName) 1214 { 1215 char[] invalidPathChars = Path.GetInvalidPathChars(); 1216 char[] DirChar = DirectoryName.ToCharArray(); 1217 foreach (char C in DirChar) 1218 { 1219 if (Array.BinarySearch(invalidPathChars, C) >= 0) 1220 { 1221 return false; 1222 } 1223 } 1224 return true; 1225 } 1226 /// <summary> 1227 /// 判断文件名中字符是否合法 1228 /// </summary> 1229 /// <param name="FileName">文件名称</param> 1230 public bool IsValidFileChars(string FileName) 1231 { 1232 char[] invalidFileChars = Path.GetInvalidFileNameChars(); 1233 char[] NameChar = FileName.ToCharArray(); 1234 foreach (char C in NameChar) 1235 { 1236 if (Array.BinarySearch(invalidFileChars, C) >= 0) 1237 { 1238 return false; 1239 } 1240 } 1241 return true; 1242 } 1243 #endregion 1244 #region 目录切换操作 1245 /// <summary> 1246 /// 进入一个目录 1247 /// </summary> 1248 /// <param name="DirectoryName"> 1249 /// 新目录的名字。 1250 /// 说明:如果新目录是当前目录的子目录,则直接指定子目录。如: SubDirectory1/SubDirectory2 ; 1251 /// 如果新目录不是当前目录的子目录,则必须从根目录一级一级的指定。如: ./NewDirectory/SubDirectory1/SubDirectory2 1252 /// </param> 1253 public bool GotoDirectory(string DirectoryName) 1254 { 1255 string CurrentWorkPath = this.DirectoryPath; 1256 try 1257 { 1258 DirectoryName = DirectoryName.Replace("\", "/"); 1259 string[] DirectoryNames = DirectoryName.Split(new char[] { '/' }); 1260 if (DirectoryNames[0] == ".") 1261 { 1262 this.DirectoryPath = "/"; 1263 if (DirectoryNames.Length == 1) 1264 { 1265 return true; 1266 } 1267 Array.Clear(DirectoryNames, 0, 1); 1268 } 1269 bool Success = false; 1270 foreach (string dir in DirectoryNames) 1271 { 1272 if (dir != null) 1273 { 1274 Success = EnterOneSubDirectory(dir); 1275 if (!Success) 1276 { 1277 this.DirectoryPath = CurrentWorkPath; 1278 return false; 1279 } 1280 } 1281 } 1282 return Success; 1283 1284 } 1285 catch (Exception ep) 1286 { 1287 this.DirectoryPath = CurrentWorkPath; 1288 ErrorMsg = ep.ToString(); 1289 throw ep; 1290 } 1291 } 1292 /// <summary> 1293 /// 从当前工作目录进入一个子目录 1294 /// </summary> 1295 /// <param name="DirectoryName">子目录名称</param> 1296 private bool EnterOneSubDirectory(string DirectoryName) 1297 { 1298 try 1299 { 1300 if (DirectoryName.IndexOf("/") >= 0 || !IsValidPathChars(DirectoryName)) 1301 { 1302 throw new Exception("目录名非法!"); 1303 } 1304 if (DirectoryName.Length > 0 && DirectoryExist(DirectoryName)) 1305 { 1306 if (!DirectoryName.EndsWith("/")) 1307 { 1308 DirectoryName += "/"; 1309 } 1310 _DirectoryPath += DirectoryName; 1311 return true; 1312 } 1313 else 1314 { 1315 return false; 1316 } 1317 } 1318 catch (Exception ep) 1319 { 1320 ErrorMsg = ep.ToString(); 1321 throw ep; 1322 } 1323 } 1324 /// <summary> 1325 /// 从当前工作目录往上一级目录 1326 /// </summary> 1327 public bool ComeoutDirectory() 1328 { 1329 if (_DirectoryPath == "/") 1330 { 1331 ErrorMsg = "当前目录已经是根目录!"; 1332 throw new Exception("当前目录已经是根目录!"); 1333 } 1334 char[] sp = new char[1] { '/' }; 1335 1336 string[] strDir = _DirectoryPath.Split(sp, StringSplitOptions.RemoveEmptyEntries); 1337 if (strDir.Length == 1) 1338 { 1339 _DirectoryPath = "/"; 1340 } 1341 else 1342 { 1343 _DirectoryPath = String.Join("/", strDir, 0, strDir.Length - 1); 1344 } 1345 return true; 1346 1347 } 1348 #endregion 1349 #region 重载WebClient,支持FTP进度 1350 internal class MyWebClient : WebClient 1351 { 1352 protected override WebRequest GetWebRequest(Uri address) 1353 { 1354 FtpWebRequest req = (FtpWebRequest) base.GetWebRequest(address); 1355 req.UsePassive = false; 1356 return req; 1357 } 1358 } 1359 #endregion 1360 } 1361 }
调用方法,目前只用上传功能: 定义全局私有变量: private clsFTP cf; 按钮事件: private void btn_upFile_Click(object sender, EventArgs e) { lb_upload.Text = "正在上传文件,请等待..."; cf = new clsFTP(new Uri("http://www.cnblogs.com/zhangjun1130/admin/ftp://192.168.43.55/"), "temp", "temp"); string localFile = Application.StartupPath.ToString() + "http://www.cnblogs.com/zhangjun1130/admin/file://output//zt.rar"; cf.UploadProgressChanged+=new clsFTP.De_UploadProgressChanged(cf_UploadProgressChanged); cf.UploadFileCompleted+=new clsFTP.De_UploadFileCompleted(cf_UploadFileCompleted); cf.UploadFileAsync(localFile, true); //调用异步传输,若有文件存在则覆盖。 } 事件捆绑,反映上传进度: public void cf_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e) { this.pgrBarFileUpload.Maximum = (int)e.TotalBytesToSend; this.pgrBarFileUpload.Value =(int) e.BytesSent; lb_upload.Text = string.Format("文件总大小:{0}k,已经上传: {1}k。", e.TotalBytesToSend/1024,e.BytesSent/1024); } public void cf_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e) { try { lb_upload.Text = "无法连接到服务器,或者用户登陆失败!"; lb_error.Text =e.Error.Message.ToString(); } catch { lb_upload.Text = "文件上传成功!"; lb_error.Text = ""; } }
源文件地址:http://www.cnblogs.com/zhangjun1130/archive/2010/03/24/1693932.html
源文件地址下有详细说明,很详细,大牛!