实现断点续传的FTP下载类(支持多线程多任务下载)
using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Windows.Forms; using System.IO; using System.Net; namespace RSGIS.FTPClient { public class MultiFtpService { #region variable private string _Server;//服务器地址 private string _UserName;//用户名 private string _Password;//密码 private string _FileUrl;//文件地址 private string _SavePath;//保存路经 Thread _Thread; private int _TaskIndex; private int _ThreadIndex; private int FileSpeed; // 实时下载速度 private FtpWebRequest ftpRequest = null; private FtpWebResponse ftpResponse = null; private Stream ftpStream = null; private int bufferSize = 2048; private int highestPercentageReached = 0; public delegate void DelegateDisplayProgress(int taskindex, int progress); public DelegateDisplayProgress WorkMethod; public delegate void DelegateDisplayFileSpeed(int taskindex, string speed); public DelegateDisplayFileSpeed FileSpeedMethod; #endregion #region Constructor public MultiFtpService(string server, string username, string password, int taskIndex, int threadIndex, string fileUrl, string savePath) { _Server = server; _UserName = username; _Password = password; _FileUrl = fileUrl; _SavePath = savePath; _TaskIndex = taskIndex; _ThreadIndex = threadIndex; } #endregion #region Functions //开始 public void Start() { long fileSize = GetLength(); _Thread = new Thread(() => { TheadDownload(_FileUrl, _SavePath, _TaskIndex, _ThreadIndex, fileSize); }); _Thread.Start(); } /// <summary> /// 暂停线程 /// </summary> public void Stop() { _Thread.Suspend(); } // 恢复线程 public void continues() { _Thread.Resume(); } //获取文件长度 private long GetLength() { Ftp ftpclient = new Ftp(_Server, _UserName, _Password); long fileSize = ftpclient.getFileSize(_FileUrl); ftpclient = null; return fileSize; } /// <summary> /// 下载 /// </summary> /// <param name="remoteFile"></param> /// <param name="localFile"></param> /// <param name="taskindex"></param> /// <param name="threadindex"></param> /// <param name="fileSize"></param> private void TheadDownload(string remoteFile, string localFile, int taskindex, int threadindex, long fileSize) { try { //续传 if (File.Exists(localFile)) { FileInfo file = new FileInfo(localFile); int locSize = Convert.ToInt32(file.Length); if (locSize.ToString() != fileSize.ToString()) { Uri FTPUri = new Uri(_Server + "/" + remoteFile); RestartDownloadFromServer(taskindex, localFile, FTPUri, file.Length, fileSize); } } else { // Create Request ftpRequest = (FtpWebRequest)FtpWebRequest.Create(_Server + "/" + remoteFile); ftpRequest.Credentials = new NetworkCredential(_UserName, _Password); ftpRequest.UseBinary = true; ftpRequest.UsePassive = true; ftpRequest.KeepAlive = true; ftpRequest.Proxy = GlobalProxySelection.GetEmptyWebProxy(); // Request Type ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile; // Get Response ftpResponse = (FtpWebResponse)ftpRequest.GetResponse(); // Get server response stream ftpStream = ftpResponse.GetResponseStream(); FileStream localFileStream = new FileStream(localFile, FileMode.Create); // Buffer for downloaded data byte[] byteBuffer = new byte[bufferSize]; int bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize); // Download File int fileSizes = Convert.ToInt32(fileSize); try { while (bytesRead > 0) { localFileStream.Write(byteBuffer, 0, bytesRead); bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize); int Complete = Convert.ToInt32(fileSizes) - bytesRead; double Fcompletes = Convert.ToDouble(Complete) / Convert.ToDouble(fileSize); double x = 1; double Fcomplete = x - Fcompletes; fileSizes = Complete; if (Fcomplete * 100 > highestPercentageReached) { WorkMethod(taskindex, Convert.ToInt32(Fcomplete * 100)); string speed = SizeConversion(Convert.ToInt64(bytesRead / 0.01)); FileSpeedMethod(taskindex, speed); } } FileInfo file = new FileInfo(localFile); int locSize = Convert.ToInt32(file.Length); if (locSize.ToString() != fileSizes.ToString()) { Uri FTPUri = new Uri(_Server + "/" + remoteFile); RestartDownloadFromServer(taskindex, localFile, FTPUri, file.Length, fileSize); } } catch (Exception ex) { throw new Exception(ex.Message); } localFileStream.Close(); ftpStream.Close(); ftpResponse.Close(); ftpRequest = null; WorkComplete(); } } catch (Exception ex) { throw new Exception(ex.Message); } //catch { } } //断点续传 private bool RestartDownloadFromServer(int taskindex, string fileName, Uri serverUri, long offset, long fileSize) { if (serverUri.Scheme != Uri.UriSchemeFtp) { return false; } // 获取ftp FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri); request.Credentials = new NetworkCredential(_UserName, _Password); request.UseBinary = true; request.UsePassive = true; request.KeepAlive = true; request.Proxy = GlobalProxySelection.GetEmptyWebProxy(); // Request Type request.Method = WebRequestMethods.Ftp.DownloadFile; request.ContentOffset = offset; FtpWebResponse response = null; try { response = (FtpWebResponse)request.GetResponse(); } catch (WebException e) { Console.WriteLine(e.Status); Console.WriteLine(e.Message); return false; } // 获取流 ftpStream = response.GetResponseStream(); //StreamReader reader = new StreamReader(newFile); //string newFileData = reader.ReadToEnd(); FileStream localFileStream = new FileStream(fileName, FileMode.Append); // Buffer for downloaded data byte[] byteBuffer = new byte[bufferSize]; int bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize); // Download File int fileSizes = Convert.ToInt32(fileSize); try { while (bytesRead > 0) { localFileStream.Write(byteBuffer, 0, bytesRead); bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize); int Complete = Convert.ToInt32(fileSizes) - bytesRead; double Fcompletes = Convert.ToDouble(Complete) / Convert.ToDouble(fileSize); double x = 1; double Fcomplete = x - Fcompletes; fileSizes = Complete; if (Fcomplete * 100 > highestPercentageReached) { Fcomplete = Fcomplete + offset / fileSize; WorkMethod(taskindex, Convert.ToInt32(Fcomplete * 100)); string speed = SizeConversion(Convert.ToInt64(bytesRead / 0.01)); FileSpeedMethod(taskindex, speed); } } } catch (Exception ex) { throw new Exception(ex.Message); } //关闭流 localFileStream.Close(); ftpStream.Close(); response.Close(); request = null; WorkComplete(); return true; } //完成 public void WorkComplete() { MessageBox.Show("文件下载成功", "Success", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } /// <summary> /// 文件大小换算 /// </summary> /// <param name="bytes">文件长度</param> /// <returns></returns> private string SizeConversion(long bytes) { int unit = 1024; if (bytes < unit) return bytes + " B"; int exp = (int)(Math.Log(bytes) / Math.Log(unit)); return String.Format("{0:F1} {1}B", bytes / Math.Pow(unit, exp), "KMGTPE"[exp - 1]); } #endregion } }