1 /// <summary> 2 /// ftp方式文件下載上傳 3 /// </summary> 4 public static class FileUpDownload 5 { 6 #region 變量屬性 7 /// <summary> 8 /// Ftp服務器ip 9 /// </summary> 10 public static string FtpServerIP = string.Empty; 11 /// <summary> 12 /// Ftp 指定用戶名 13 /// </summary> 14 public static string FtpUserID = string.Empty; 15 /// <summary> 16 /// Ftp 指定用戶密碼 17 /// </summary> 18 public static string FtpPassword = string.Empty; 19 20 //public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2); 21 #endregion 22 23 #region 從FTP服務器下載文件,指定本地路徑和本地文件名 24 /// <summary> 25 /// 從FTP服務器下載文件,指定本地路徑和本地文件名 26 /// </summary> 27 /// <param name="remoteFileName">遠程文件名</param> 28 /// <param name="localFileName">保存本地的文件名(包含路徑)</param> 29 /// <param name="ifCredential">是否啟用身份驗證(false:表示允許用戶匿名下載)</param> 30 /// <param name="updateProgress">報告進度的處理(第一個參數:總大小,第二個參數:當前進度)</param> 31 /// <returns>是否下載成功</returns> 32 public static bool FtpDownload(string remoteFileName, string localFileName, bool ifCredential, Action<int, int> updateProgress = null) 33 { 34 FtpWebRequest reqFTP, ftpsize; 35 Stream ftpStream = null; 36 FtpWebResponse response = null; 37 FileStream outputStream = null; 38 try 39 { 40 outputStream = new FileStream(localFileName, FileMode.Create); 41 if (FtpServerIP == null || FtpServerIP.Trim().Length == 0) 42 { 43 throw new Exception("ftp下載目標服務器地址未設置!"); 44 } 45 Uri uri = new Uri("ftp://" + FtpServerIP + "/" + remoteFileName); 46 ftpsize = (FtpWebRequest)FtpWebRequest.Create(uri); 47 ftpsize.UseBinary = true; 48 49 reqFTP = (FtpWebRequest)FtpWebRequest.Create(uri); 50 reqFTP.UseBinary = true; 51 reqFTP.KeepAlive = false; 52 if (ifCredential)//使用用戶身份認證 53 { 54 ftpsize.Credentials = new NetworkCredential(FtpUserID, FtpPassword); 55 reqFTP.Credentials = new NetworkCredential(FtpUserID, FtpPassword); 56 } 57 58 //SSL 59 reqFTP.EnableSsl = true; 60 ftpsize.EnableSsl = true; 61 //證書回調方法 62 ServicePointManager.ServerCertificateValidationCallback = ServicePointManager_ServerCertificateValidationCallback; 63 64 //證書 65 // X509Certificate cert = X509Certificate.CreateFromCertFile(Application.StartupPath + "/MyCertDir/certificate1.cer"); 66 //X509Certificate cert = X509Certificate.CreateFromCertFile(@"C:\MyCertDir\MyCertFile1.cer"); 67 //X509CertificateCollection certCollection = new X509CertificateCollection(); 68 // certCollection.Add(cert); 69 // reqFTP.ClientCertificates = certCollection; 70 71 ftpsize.Method = WebRequestMethods.Ftp.GetFileSize; 72 FtpWebResponse re = (FtpWebResponse)ftpsize.GetResponse(); 73 long totalBytes = re.ContentLength; 74 re.Close(); 75 76 reqFTP.Method = WebRequestMethods.Ftp.DownloadFile; 77 response = (FtpWebResponse)reqFTP.GetResponse(); 78 ftpStream = response.GetResponseStream(); 79 80 //更新進度 81 82 //updateProgress(0, 0); 83 if (updateProgress != null) 84 { 85 updateProgress((int)totalBytes, 0);//更新進度條 86 } 87 long totalDownloadedByte = 0; 88 int bufferSize = 2048; 89 int readCount; 90 byte[] buffer = new byte[bufferSize]; 91 readCount = ftpStream.Read(buffer, 0, bufferSize); 92 while (readCount > 0) 93 { 94 totalDownloadedByte = readCount + totalDownloadedByte; 95 outputStream.Write(buffer, 0, readCount); 96 //更新進度 97 if (updateProgress != null) 98 { 99 updateProgress((int)totalBytes, (int)totalDownloadedByte);//更新進度條 100 } 101 readCount = ftpStream.Read(buffer, 0, bufferSize); 102 } 103 ftpStream.Close(); 104 outputStream.Close(); 105 response.Close(); 106 return true; 107 108 } 109 catch (Exception ex) 110 { 111 return false; 112 throw; 113 } 114 finally 115 { 116 if (ftpStream != null) 117 { 118 ftpStream.Close(); 119 } 120 if (outputStream != null) 121 { 122 outputStream.Close(); 123 } 124 if (response != null) 125 { 126 response.Close(); 127 } 128 } 129 } 130 131 public static bool ServicePointManager_ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) 132 { 133 bool allowCertificate = true; 134 135 if (sslPolicyErrors != SslPolicyErrors.None) 136 { 137 Console.WriteLine("接受的證書錯誤:"); 138 if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) == SslPolicyErrors.RemoteCertificateNameMismatch) 139 { 140 Console.WriteLine("\t證書 {0} 不匹配.", certificate.Subject); 141 } 142 143 if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors) 144 { 145 Console.WriteLine("\t證書以下錯誤信息:"); 146 foreach (X509ChainStatus chainStatus in chain.ChainStatus) 147 { 148 Console.WriteLine("\t\t{0}", chainStatus.StatusInformation); 149 150 if (chainStatus.Status == X509ChainStatusFlags.Revoked) 151 { 152 allowCertificate = false; 153 } 154 } 155 } 156 157 if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) == SslPolicyErrors.RemoteCertificateNotAvailable) 158 { 159 Console.WriteLine("沒有可用的證書。"); 160 allowCertificate = false; 161 } 162 163 Console.WriteLine(); 164 } 165 166 return allowCertificate; 167 } 168 169 /// <summary> 170 /// 從FTP服務器下載文件,指定本地路徑和本地文件名(支持斷點下載) 171 /// </summary> 172 /// <param name="remoteFileName">遠程文件名</param> 173 /// <param name="localFileName">保存本地的文件名(包含路徑)</param> 174 /// <param name="ifCredential">是否啟用身份驗證(false:表示允許用戶匿名下載)</param> 175 /// <param name="size">已下載文件流大小</param> 176 /// <param name="updateProgress">報告進度的處理(第一個參數:總大小,第二個參數:當前進度)</param> 177 /// <returns>是否下載成功</returns> 178 public static bool FtpBrokenDownload(string remoteFileName, string localFileName, bool ifCredential, long size, Action<int, int> updateProgress = null) 179 { 180 FtpWebRequest reqFTP, ftpsize; 181 Stream ftpStream = null; 182 FtpWebResponse response = null; 183 FileStream outputStream = null; 184 185 try 186 { 187 outputStream = new FileStream(localFileName, FileMode.Append); 188 if (FtpServerIP == null || FtpServerIP.Trim().Length == 0) 189 { 190 throw new Exception("ftp下載目標服務器地址未設置!"); 191 } 192 Uri uri = new Uri("ftp://" + FtpServerIP + "/" + remoteFileName); 193 ftpsize = (FtpWebRequest)FtpWebRequest.Create(uri); 194 ftpsize.UseBinary = true; 195 ftpsize.ContentOffset = size; 196 197 reqFTP = (FtpWebRequest)FtpWebRequest.Create(uri); 198 reqFTP.UseBinary = true; 199 reqFTP.KeepAlive = false; 200 reqFTP.ContentOffset = size; 201 if (ifCredential)//使用用戶身份認證 202 { 203 ftpsize.Credentials = new NetworkCredential(FtpUserID, FtpPassword); 204 reqFTP.Credentials = new NetworkCredential(FtpUserID, FtpPassword); 205 } 206 //SSL 207 reqFTP.EnableSsl = true; 208 ftpsize.EnableSsl = true; 209 //證書回調方法 210 ServicePointManager.ServerCertificateValidationCallback = ServicePointManager_ServerCertificateValidationCallback; 211 212 ftpsize.Method = WebRequestMethods.Ftp.GetFileSize; 213 FtpWebResponse re = (FtpWebResponse)ftpsize.GetResponse(); 214 long totalBytes = re.ContentLength; 215 re.Close(); 216 217 reqFTP.Method = WebRequestMethods.Ftp.DownloadFile; 218 response = (FtpWebResponse)reqFTP.GetResponse(); 219 ftpStream = response.GetResponseStream(); 220 221 //更新進度 222 if (updateProgress != null) 223 { 224 updateProgress((int)totalBytes, 0);//更新進度條 225 } 226 long totalDownloadedByte = 0; 227 int bufferSize = 2048; 228 int readCount; 229 byte[] buffer = new byte[bufferSize]; 230 readCount = ftpStream.Read(buffer, 0, bufferSize); 231 while (readCount > 0) 232 { 233 totalDownloadedByte = readCount + totalDownloadedByte; 234 outputStream.Write(buffer, 0, readCount); 235 //更新進度 236 if (updateProgress != null) 237 { 238 updateProgress((int)totalBytes, (int)totalDownloadedByte);//更新進度條 239 } 240 readCount = ftpStream.Read(buffer, 0, bufferSize); 241 } 242 ftpStream.Close(); 243 outputStream.Close(); 244 response.Close(); 245 return true; 246 } 247 catch (Exception ex) 248 { 249 return false; 250 throw; 251 } 252 finally 253 { 254 if (ftpStream != null) 255 { 256 ftpStream.Close(); 257 } 258 if (outputStream != null) 259 { 260 outputStream.Close(); 261 } 262 if (response != null) 263 { 264 response.Close(); 265 } 266 } 267 268 } 269 270 /// <summary> 271 /// 從FTP服務器下載文件,指定本地路徑和本地文件名 272 /// </summary> 273 /// <param name="remoteFileName">遠程文件名</param> 274 /// <param name="localFileName">保存本地的文件名(包含路徑)</param> 275 /// <param name="ifCredential">是否啟用身份驗證(false:表示允許用戶匿名下載)</param> 276 /// <param name="updateProgress">報告進度的處理(第一個參數:總大小,第二個參數:當前進度)</param> 277 /// <param name="brokenOpen">是否斷點下載:true 會在localFileName 找是否存在已經下載的文件,並計算文件流大小</param> 278 /// <returns>是否下載成功</returns> 279 public static bool FtpDownload(string remoteFileName, string localFileName, bool ifCredential, bool brokenOpen, Action<int, int> updateProgress = null) 280 { 281 if (brokenOpen) 282 { 283 try 284 { 285 long size = 0; 286 if (File.Exists(localFileName)) 287 { 288 using (FileStream outputStream = new FileStream(localFileName, FileMode.Open)) 289 { 290 size = outputStream.Length; 291 } 292 } 293 return FtpBrokenDownload(remoteFileName, localFileName, ifCredential, size, updateProgress); 294 } 295 catch 296 { 297 throw; 298 } 299 } 300 else 301 { 302 return FtpDownload(remoteFileName, localFileName, ifCredential, updateProgress); 303 } 304 } 305 306 #endregion 307 308 #region 上傳文件到FTP服務器 309 /// <summary> 310 /// 上傳文件到FTP服務器 311 /// </summary> 312 /// <param name="localFullPath">本地帶有完整路徑的文件名</param> 313 /// <param name="updateProgress">報告進度的處理(第一個參數:總大小,第二個參數:當前進度)</param> 314 /// <returns>是否下載成功</returns> 315 public static bool FtpUploadFile(string localFullPathName, Action<int, int> updateProgress = null) 316 { 317 FtpWebRequest reqFTP; 318 Stream stream = null; 319 FtpWebResponse response = null; 320 FileStream fs = null; 321 322 try 323 { 324 FileInfo finfo = new FileInfo(localFullPathName); 325 if (FtpServerIP == null || FtpServerIP.Trim().Length == 0) 326 { 327 throw new Exception("ftp上傳目標服務器地址未設置!"); 328 } 329 Uri uri = new Uri("ftp://" + FtpServerIP + "/" + finfo.Name); 330 reqFTP = (FtpWebRequest)FtpWebRequest.Create(uri); 331 reqFTP.KeepAlive = false; 332 reqFTP.UseBinary = true; 333 reqFTP.Credentials = new NetworkCredential(FtpUserID, FtpPassword);//用戶,密碼 334 reqFTP.Method = WebRequestMethods.Ftp.UploadFile;//向服務器發出下載請求命令 335 reqFTP.ContentLength = finfo.Length;//為request指定上傳文件的大小 336 337 reqFTP.EnableSsl = true; 338 //證書回調方法 339 ServicePointManager.ServerCertificateValidationCallback = ServicePointManager_ServerCertificateValidationCallback; 340 341 response = reqFTP.GetResponse() as FtpWebResponse; 342 reqFTP.ContentLength = finfo.Length; 343 int buffLength = 1024; 344 byte[] buff = new byte[buffLength]; 345 int contentLen; 346 fs = finfo.OpenRead(); 347 stream = reqFTP.GetRequestStream(); 348 contentLen = fs.Read(buff, 0, buffLength); 349 int allbye = (int)finfo.Length; 350 //更新進度 351 if (updateProgress != null) 352 { 353 updateProgress((int)allbye, 0);//更新進度條 354 } 355 int startbye = 0; 356 while (contentLen != 0) 357 { 358 startbye = contentLen + startbye; 359 stream.Write(buff, 0, contentLen); 360 //更新進度 361 if (updateProgress != null) 362 { 363 updateProgress((int)allbye, (int)startbye);//更新進度條 364 } 365 contentLen = fs.Read(buff, 0, buffLength); 366 } 367 stream.Close(); 368 fs.Close(); 369 response.Close(); 370 return true; 371 372 } 373 catch (Exception ex) 374 { 375 return false; 376 throw; 377 } 378 finally 379 { 380 if (fs != null) 381 { 382 fs.Close(); 383 } 384 if (stream != null) 385 { 386 stream.Close(); 387 } 388 if (response != null) 389 { 390 response.Close(); 391 } 392 } 393 } 394 395 /// <summary> 396 /// 上傳文件到FTP服務器(斷點續傳) 397 /// </summary> 398 /// <param name="localFullPath">本地文件全路徑名稱:C:\Users\JianKunKing\Desktop\IronPython腳本測試工具</param> 399 /// <param name="remoteFilepath">遠程文件所在文件夾路徑</param> 400 /// <param name="updateProgress">報告進度的處理(第一個參數:總大小,第二個參數:當前進度)</param> 401 /// <returns></returns> 402 public static bool FtpUploadBroken(string localFullPath, string remoteFilepath, Action<int, int> updateProgress = null) 403 { 404 if (remoteFilepath == null) 405 { 406 remoteFilepath = ""; 407 } 408 string newFileName = string.Empty; 409 bool success = true; 410 FileInfo fileInf = new FileInfo(localFullPath); 411 long allbye = (long)fileInf.Length; 412 if (fileInf.Name.IndexOf("#") == -1) 413 { 414 newFileName = RemoveSpaces(fileInf.Name); 415 } 416 else 417 { 418 newFileName = fileInf.Name.Replace("#", "#"); 419 newFileName = RemoveSpaces(newFileName); 420 } 421 long startfilesize = GetFileSize(newFileName, remoteFilepath); 422 if (startfilesize >= allbye) 423 { 424 return false; 425 } 426 long startbye = startfilesize; 427 //更新進度 428 if (updateProgress != null) 429 { 430 updateProgress((int)allbye, (int)startfilesize);//更新進度條 431 } 432 433 string uri; 434 if (remoteFilepath.Length == 0) 435 { 436 uri = "ftp://" + FtpServerIP + "/" + newFileName; 437 } 438 else 439 { 440 uri = "ftp://" + FtpServerIP + "/" + remoteFilepath + "/" + newFileName; 441 } 442 FtpWebRequest reqFTP; 443 // 根據uri創建FtpWebRequest對象 444 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); 445 // ftp用戶名和密碼 446 reqFTP.Credentials = new NetworkCredential(FtpUserID, FtpPassword); 447 // 默認為true,連接不會被關閉 448 // 在一個命令之后被執行 449 reqFTP.KeepAlive = false; 450 // 指定執行什么命令 451 reqFTP.Method = WebRequestMethods.Ftp.AppendFile; 452 // 指定數據傳輸類型 453 reqFTP.UseBinary = true; 454 // 上傳文件時通知服務器文件的大小 455 reqFTP.ContentLength = fileInf.Length; 456 int buffLength = 2048;// 緩沖大小設置為2kb 457 byte[] buff = new byte[buffLength]; 458 // 打開一個文件流 (System.IO.FileStream) 去讀上傳的文件 459 FileStream fs = fileInf.OpenRead(); 460 Stream strm = null; 461 try 462 { 463 // 把上傳的文件寫入流 464 strm = reqFTP.GetRequestStream(); 465 // 每次讀文件流的2kb 466 fs.Seek(startfilesize, 0); 467 int contentLen = fs.Read(buff, 0, buffLength); 468 // 流內容沒有結束 469 while (contentLen != 0) 470 { 471 // 把內容從file stream 寫入 upload stream 472 strm.Write(buff, 0, contentLen); 473 contentLen = fs.Read(buff, 0, buffLength); 474 startbye += contentLen; 475 //更新進度 476 if (updateProgress != null) 477 { 478 updateProgress((int)allbye, (int)startbye);//更新進度條 479 } 480 } 481 // 關閉兩個流 482 strm.Close(); 483 fs.Close(); 484 } 485 catch 486 { 487 success = false; 488 throw; 489 } 490 finally 491 { 492 if (fs != null) 493 { 494 fs.Close(); 495 } 496 if (strm != null) 497 { 498 strm.Close(); 499 } 500 } 501 return success; 502 } 503 504 /// <summary> 505 /// 去除空格 506 /// </summary> 507 /// <param name="str"></param> 508 /// <returns></returns> 509 private static string RemoveSpaces(string str) 510 { 511 string a = ""; 512 CharEnumerator CEnumerator = str.GetEnumerator(); 513 while (CEnumerator.MoveNext()) 514 { 515 byte[] array = new byte[1]; 516 array = System.Text.Encoding.ASCII.GetBytes(CEnumerator.Current.ToString()); 517 int asciicode = (short)(array[0]); 518 if (asciicode != 32) 519 { 520 a += CEnumerator.Current.ToString(); 521 } 522 } 523 string sdate = System.DateTime.Now.Year.ToString() + System.DateTime.Now.Month.ToString() + System.DateTime.Now.Day.ToString() + System.DateTime.Now.Hour.ToString() 524 + System.DateTime.Now.Minute.ToString() + System.DateTime.Now.Second.ToString() + System.DateTime.Now.Millisecond.ToString(); 525 return a.Split('.')[a.Split('.').Length - 2] + "." + a.Split('.')[a.Split('.').Length - 1]; 526 } 527 528 /// <summary> 529 /// 獲取已上傳文件大小 530 /// </summary> 531 /// <param name="filename">文件名稱</param> 532 /// <param name="path">服務器文件路徑</param> 533 /// <returns></returns> 534 public static long GetFileSize(string filename, string remoteFilepath) 535 { 536 long filesize = 0; 537 try 538 { 539 FtpWebRequest reqFTP; 540 FileInfo fi = new FileInfo(filename); 541 string uri; 542 if (remoteFilepath.Length == 0) 543 { 544 uri = "ftp://" + FtpServerIP + "/" + fi.Name; 545 } 546 else 547 { 548 uri = "ftp://" + FtpServerIP + "/" + remoteFilepath + "/" + fi.Name; 549 } 550 reqFTP = (FtpWebRequest)FtpWebRequest.Create(uri); 551 reqFTP.KeepAlive = false; 552 reqFTP.UseBinary = true; 553 reqFTP.Credentials = new NetworkCredential(FtpUserID, FtpPassword);//用戶,密碼 554 reqFTP.Method = WebRequestMethods.Ftp.GetFileSize; 555 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); 556 filesize = response.ContentLength; 557 return filesize; 558 } 559 catch 560 { 561 return 0; 562 } 563 } 564 565 566 #endregion