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