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:MyCertDirMyCertFile1.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(" 证书 {0} 不匹配.", certificate.Subject); 141 } 142 143 if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors) 144 { 145 Console.WriteLine(" 证书以下错误信息:"); 146 foreach (X509ChainStatus chainStatus in chain.ChainStatus) 147 { 148 Console.WriteLine(" {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:UsersJianKunKingDesktopIronPython脚本测试工具</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