实现简单的FTP多线程下载和上传
常想在园子里写点什么东西,但每当提笔,便已觉得肤浅,不敢写出来怡笑大方。对于各位战斗在软件第一线的道友们来说,本人只能算得上是一个业余选手,也许连业余也算不上。始终很自卑,觉得跟大家的水平相差太远。一直以来,对计算机都非常有兴趣,中专毕业以后,通过书籍和网上学了些皮毛。说来惭愧,中专三年,玩了三年游戏,严格地说,只能算是初中毕业。当年的愿望是希望能够从事软件相关的工作,无奈,学历低,专业也不对口。混迹于江湖N年,一直未能如愿。现在在一家工厂里从事管理工作,偶尔写点程序,协助管理。一转眼,毕业十多年了,光阴似箭哪。闲话扯多了,今天,鼓起勇气,写点东西,希望能够得到大家的指导。
本想找一个相对完整的FTP实现的代码,集成到我工厂的ERP软件里,在网上找了很久,也没有合适的,只好自己动手做一个。以下界面只是测试界面,FTP的管理已经封装成单独的类,可以灵活调用。实现的界面如下图,使用WPF做界面,的确很方便,很灵活。接触WPF真有点相见恨晚的感觉。FTP服务器使用IIS架设,关于如何架设FTP服务器,网上有很多资料,相当简单,在此不多缀述。源码下载:https://files.cnblogs.com/laoyang999/WpfApplication1.zip
界面代码如下:
1 <Window x:Class="WpfApplication1.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="MainWindow" Height="350" Width="525" Closing="Window_Closing"> 5 <Grid> 6 <Grid.RowDefinitions> 7 <RowDefinition Height="30"/> 8 <RowDefinition Height="30"/> 9 <RowDefinition/> 10 </Grid.RowDefinitions> 11 12 <StackPanel Orientation="Horizontal" Grid.Row="0" > 13 <TextBlock Text="ServerIP:" Margin="3" VerticalAlignment="Center"/> 14 <TextBox x:Name="serverIP" Text="192.168.1.100" VerticalAlignment="Center" 15 Width="100"/> 16 <TextBlock Text="UserID:" Margin="3" VerticalAlignment="Center"/> 17 <TextBox x:Name="userID" Text="administrator" VerticalAlignment="Center" 18 Width="80"/> 19 <TextBlock Text="Password:" Margin="3" VerticalAlignment="Center"/> 20 <PasswordBox x:Name="pwd" Password="123456" Width="65" Margin="3" VerticalAlignment="Center"/> 21 <Button x:Name="btnConnect" Margin="3" Content="连接" VerticalAlignment="Center" Click="Connect_click" /> 22 </StackPanel> 23 <Grid Grid.Row="1" x:Name="gdUpLoad"> 24 <Border BorderBrush="Gray" BorderThickness="0,1,0,0" Margin="3,0,3,0"/> 25 <StackPanel Orientation="Horizontal"> 26 <Button x:Name="btnUpload" Content="上传" Width="50" Margin="5,4,2,4" Tag="{Binding }" Click="btn_UpLoad"/> 27 <StackPanel x:Name="filePanel" Visibility="Hidden"> 28 <TextBlock Text="{Binding fileName}" Margin="2"/> 29 <ProgressBar Maximum="100" Height="8" Value="{Binding complete}"/> 30 </StackPanel> 31 <TextBlock Text="{Binding DownLoadStatus}" Margin="3" VerticalAlignment="Center" Foreground="Blue"/> 32 </StackPanel> 33 </Grid> 34 <ListBox Grid.Row="2" x:Name="fileList" 35 Margin="3" BorderBrush="Black" BorderThickness="1"> 36 <ListBox.Background> 37 <LinearGradientBrush EndPoint="0.497,0.907" StartPoint="0.5,0"> 38 <GradientStop Color="#FFE5DF9E" Offset="0"/> 39 <GradientStop Color="#FFFEFFF9" Offset="1"/> 40 </LinearGradientBrush> 41 </ListBox.Background> 42 <ListBox.ItemTemplate> 43 <DataTemplate> 44 <Grid> 45 <Grid.ColumnDefinitions> 46 <ColumnDefinition Width="200"/> 47 <ColumnDefinition MinWidth="80"/> 48 <ColumnDefinition MinWidth="50"/> 49 </Grid.ColumnDefinitions> 50 <TextBlock Text="{Binding fileName}" Grid.Column="0"/> 51 <ProgressBar Grid.Column="1" Margin="2" Height="10" Maximum="100" VerticalAlignment="Center" 52 Value="{Binding complete}"/> 53 <Button x:Name="btn" Grid.Column="2" Content="{Binding DownLoadStatus}" 54 Margin="2,0,2,0" VerticalAlignment="Center" Height="20" 55 Tag="{Binding }" 56 Click="btn_Click"/> 57 </Grid> 58 </DataTemplate> 59 </ListBox.ItemTemplate> 60 </ListBox> 61 </Grid> 62 </Window>
首先,建立下FTP管理的类,以下这些代码是从网上Down下来的,有些东西,别人已经做好了现成的,就没必要重新写一遍了,多浪费时间啊。但是,从网上复制的这这段代码存在一些问题。第一,获取文件列表的时候,会把文件夹都一起显示出来;第二,上传和下载没有进度报告;对此,我做了一些修改。针对进度报告,采取了事件触发的方式。对于获取文件列表(不包含文件夹),在网上找了N多代码,似乎都有问题。后来,我用了一个取巧的办法,用WebRequestMethods.Ftp.ListDirectoryDetails 的方法,获取目录明细,明细中包含<DIR>的就是文件夹了,把文件夹提取出来,再跟获取的文件列表进行比对,名字相同的,就剔除。
以下是FTP管理类
1 //FTP操作 2 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Text; 7 using System.IO; 8 using System.Net; 9 10 namespace WpfApplication1 11 { 12 public class FTPHelper 13 { 14 15 //下载进度变化 16 public delegate void OnDonwnLoadProcessHandle(object sender); 17 //上传进度变化 18 public delegate void OnUpLoadProcessHandle(object sender); 19 20 public event OnDonwnLoadProcessHandle OnDownLoadProgressChanged; 21 public event OnUpLoadProcessHandle OnUpLoadProgressChanged; 22 23 string ftpServerIP; 24 string ftpRemotePath; 25 string ftpUserID; 26 string ftpPassword; 27 string ftpURI; 28 int dowLoadComplete; //为图方便,上传和下载都用这个数据 29 bool DownLoadCancel; 30 bool _UPLoadCancel; 31 int upLoadComplete; 32 33 //下载进度 34 public int DownComplete 35 { 36 get { return dowLoadComplete; } 37 } 38 //上传进度 39 public int UpLoadComplete 40 { 41 get { return upLoadComplete; } 42 } 43 44 //取消状态 45 46 public bool DownLoadCancelStatus 47 { 48 get { return DownLoadCancel; } 49 } 50 //取消上传状态 51 public bool UpLoadCancel 52 { 53 get { return _UPLoadCancel; } 54 } 55 /// <summary> 56 /// 初始化 57 /// </summary> 58 /// <param name="server"></param> 59 /// <param name="remotePath"></param> 60 /// <param name="userID"></param> 61 /// <param name="password"></param> 62 public FTPHelper(string server, string remotePath, string userID, string password) 63 { 64 ftpServerIP = server; 65 ftpRemotePath = remotePath; 66 ftpUserID = userID; 67 ftpPassword = password; 68 ftpURI = "ftp://" + ftpServerIP + "/" + remotePath ; 69 dowLoadComplete = 0; 70 DownLoadCancel = false;//下载操作是否取消 71 _UPLoadCancel = false;//上传是否取消 72 } 73 74 //上传文件 75 public string UploadFile(string[] filePaths) 76 { 77 StringBuilder sb = new StringBuilder(); 78 if (filePaths != null && filePaths.Length > 0) 79 { 80 foreach (var file in filePaths) 81 { 82 sb.Append(Upload(file)); 83 84 } 85 } 86 return sb.ToString(); 87 } 88 89 /// <summary> 90 /// 上传文件 91 /// </summary> 92 /// <param name="filename"></param> 93 public string Upload(string filename) 94 { 95 FileInfo fileInf = new FileInfo(filename); 96 97 if (!fileInf.Exists) 98 { 99 return filename + " 不存在!\n"; 100 } 101 102 long fileSize = fileInf.Length;//获取本地文件的大小 103 104 string uri = ftpURI + fileInf.Name; 105 FtpWebRequest reqFTP; 106 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); 107 108 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 109 reqFTP.KeepAlive = false; 110 reqFTP.Method = WebRequestMethods.Ftp.UploadFile; 111 reqFTP.UseBinary = true; 112 reqFTP.UsePassive = false; //选择主动还是被动模式 113 //Entering Passive Mode 114 reqFTP.ContentLength = fileInf.Length; 115 int buffLength = 2048; 116 byte[] buff = new byte[buffLength]; 117 int contentLen; 118 FileStream fs = fileInf.OpenRead(); 119 try 120 { 121 Stream strm = reqFTP.GetRequestStream(); 122 contentLen = fs.Read(buff, 0, buffLength); 123 long hasUpLoad = contentLen; 124 while (contentLen != 0) 125 { 126 strm.Write(buff, 0, contentLen); 127 contentLen = fs.Read(buff, 0, buffLength); 128 hasUpLoad += contentLen; 129 upLoadComplete= (int)((Single)hasUpLoad / (Single)fileSize * 100.0); 130 if (this.OnUpLoadProgressChanged != null) 131 { 132 OnUpLoadProgressChanged(this); 133 } 134 if (this.UpLoadCancel == true) //是否已经取消上传 135 { 136 strm.Close(); 137 fs.Close(); 138 if (FileExist(fileInf.Name))//删除服务器中已经存在的文件 139 { Delete(fileInf.Name); } 140 return ""; 141 } 142 } 143 strm.Close(); 144 fs.Close(); 145 } 146 catch 147 { 148 return "同步 " + filename + "时连接不上服务器!\n"; 149 } 150 return ""; 151 } 152 153 /// <summary> 154 /// 下载 155 /// </summary> 156 /// <param name="filePath"></param> 157 /// <param name="fileName"></param> 158 public void Download(string filePath, string fileName) 159 { 160 FtpWebRequest reqFTP; 161 try 162 { 163 FileStream outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create); 164 165 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + fileName)); 166 reqFTP.Method = WebRequestMethods.Ftp.DownloadFile; 167 reqFTP.UseBinary = true; 168 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 169 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); 170 Stream ftpStream = response.GetResponseStream(); 171 long cl = response.ContentLength; 172 int bufferSize = 2048; 173 int readCount; 174 byte[] buffer = new byte[bufferSize]; 175 176 readCount = ftpStream.Read(buffer, 0, bufferSize); 177 //获取文件大小 178 long fileLength = GetFileSize(fileName); 179 long hasDonwnload = (long)readCount; 180 181 while (readCount > 0) 182 { 183 outputStream.Write(buffer, 0, readCount); 184 readCount = ftpStream.Read(buffer, 0, bufferSize); 185 hasDonwnload += (long)readCount; 186 //获取下载进度 187 this.dowLoadComplete = (int)((Single)hasDonwnload / (Single)fileLength * 100.0); 188 if (OnDownLoadProgressChanged != null) 189 { 190 OnDownLoadProgressChanged(this);//触发事件,用于客户端获取下载进度 191 } 192 if (DownLoadCancel == true) 193 { 194 ftpStream.Close(); 195 outputStream.Close(); 196 response.Close(); 197 //删除文件 198 if (File.Exists(filePath + "\\" + fileName)) 199 { 200 File.Delete(filePath + "\\" + fileName); 201 } 202 return;//退出程序 203 } 204 } 205 206 ftpStream.Close(); 207 outputStream.Close(); 208 response.Close(); 209 } 210 catch (Exception ex) 211 { 212 throw new Exception(ex.Message); 213 } 214 } 215 216 //取消下载 217 public void CancelDownLoad() 218 { 219 this.DownLoadCancel = true; 220 } 221 222 //取消上传 223 public void CancelUpLoad() 224 { 225 this._UPLoadCancel = true; 226 } 227 /// <summary> 228 /// 删除文件 229 /// </summary> 230 /// <param name="fileName"></param> 231 public void Delete(string fileName) 232 { 233 try 234 { 235 string uri = ftpURI + fileName; 236 FtpWebRequest reqFTP; 237 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); 238 239 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 240 reqFTP.KeepAlive = false; 241 reqFTP.Method = WebRequestMethods.Ftp.DeleteFile; 242 243 string result = String.Empty; 244 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); 245 long size = response.ContentLength; 246 Stream datastream = response.GetResponseStream(); 247 StreamReader sr = new StreamReader(datastream); 248 result = sr.ReadToEnd(); 249 sr.Close(); 250 datastream.Close(); 251 response.Close(); 252 } 253 catch (Exception ex) 254 { 255 throw new Exception(ex.Message); 256 } 257 } 258 259 /// <summary> 260 /// 获取当前目录下明细(包含文件和文件夹) 261 /// </summary> 262 /// <returns></returns> 263 public string[] GetFilesDetailList() 264 { 265 try 266 { 267 StringBuilder result = new StringBuilder(); 268 FtpWebRequest ftp; 269 ftp = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI)); 270 ftp.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 271 ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails; 272 WebResponse response = ftp.GetResponse(); 273 StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.GetEncoding("gb2312")); 274 string line = reader.ReadLine(); 275 line = reader.ReadLine(); 276 line = reader.ReadLine(); 277 while (line != null) 278 { 279 result.Append(line); 280 result.Append("\n"); 281 line = reader.ReadLine(); 282 } 283 result.Remove(result.ToString().LastIndexOf("\n"), 1); 284 reader.Close(); 285 response.Close(); 286 return result.ToString().Split('\n'); 287 } 288 catch (Exception ex) 289 { 290 throw new Exception(ex.Message); 291 } 292 } 293 294 /// <summary> 295 /// 获取当前目录下文件列表(仅文件) 296 /// </summary> 297 /// <returns></returns> 298 public List<string> GetFileList(string mask) 299 { 300 StringBuilder result = new StringBuilder(); 301 FtpWebRequest reqFTP; 302 try 303 { 304 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI)); 305 reqFTP.UseBinary = true; 306 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 307 reqFTP.Method = WebRequestMethods.Ftp.ListDirectory; 308 WebResponse response = reqFTP.GetResponse(); 309 StreamReader reader = new StreamReader(response.GetResponseStream(),System.Text.Encoding.GetEncoding("gb2312")); 310 311 string line = reader.ReadLine(); 312 while (line != null) 313 { 314 if (mask.Trim() != string.Empty && mask.Trim() != "*.*") 315 { 316 string mask_ = mask.Substring(0, mask.IndexOf("*")); 317 if (line.Substring(0, mask_.Length) == mask_) 318 { 319 result.Append(line); 320 result.Append("\n"); 321 } 322 } 323 else 324 { 325 result.Append(line); 326 result.Append("\n"); 327 } 328 329 line = reader.ReadLine(); 330 } 331 result.Remove(result.ToString().LastIndexOf('\n'), 1); 332 reader.Close(); 333 response.Close(); 334 335 string[] files= result.ToString().Split('\n'); 336 string[] Directors = GetDirectoryList(); 337 List<string> tempList = new List<string>(); 338 for (int i = 0; i < files.Length; i++) 339 { 340 bool isFile = true; 341 for (int j = 0; j < Directors.Length; j++) 342 { 343 if (files[i].Trim() == Directors[j].Trim()) 344 { isFile = false; } 345 } 346 if (isFile == true) 347 { 348 tempList.Add(files[i]); 349 } 350 } 351 return tempList; 352 } 353 catch (Exception ex) 354 { 355 if (ex.Message.Trim() != "远程服务器返回错误: (550) 文件不可用(例如,未找到文件,无法访问文件)。") 356 { 357 throw new Exception(ex.Message); 358 } 359 throw new Exception("获取文件列表出错,错误:" + ex.Message); 360 } 361 } 362 363 /// <summary> 364 /// 获取当前目录下所有的文件夹列表(仅文件夹) 365 /// </summary> 366 /// <returns></returns> 367 public string[] GetDirectoryList() 368 { 369 string[] drectory = GetFilesDetailList(); 370 string m = string.Empty; 371 foreach (string str in drectory) 372 { 373 if (str.Contains("<DIR>")) 374 { 375 m += str.Substring(39).Trim() + "\n"; 376 } 377 } 378 m = m.Substring(0, m.Length - 1); 379 return m.Split('\n'); 380 } 381 382 /// <summary> 383 /// 判断当前目录下指定的子目录是否存在 384 /// </summary> 385 /// <param name="RemoteDirectoryName">指定的目录名</param> 386 public bool DirectoryExist(string RemoteDirectoryName) 387 { 388 string[] dirList = GetDirectoryList(); 389 foreach (string str in dirList) 390 { 391 if (str.Trim() == RemoteDirectoryName.Trim()) 392 { 393 return true; 394 } 395 } 396 return false; 397 } 398 399 /// <summary> 400 /// 判断当前目录下指定的文件是否存在 401 /// </summary> 402 /// <param name="RemoteFileName">远程文件名</param> 403 public bool FileExist(string RemoteFileName) 404 { 405 List<string> fileList = GetFileList("*.*"); 406 foreach (string str in fileList) 407 { 408 if (str.Trim() == RemoteFileName.Trim()) 409 { 410 return true; 411 } 412 } 413 return false; 414 } 415 416 /// <summary> 417 /// 创建文件夹 418 /// </summary> 419 /// <param name="dirName"></param> 420 public void MakeDir(string dirName) 421 { 422 FtpWebRequest reqFTP; 423 try 424 { 425 // dirName = name of the directory to create. 426 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + dirName)); 427 reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory; 428 reqFTP.UseBinary = true; 429 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 430 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); 431 Stream ftpStream = response.GetResponseStream(); 432 433 ftpStream.Close(); 434 response.Close(); 435 } 436 catch (Exception ex) 437 { 438 throw new Exception(ex.Message); 439 } 440 } 441 442 /// <summary> 443 /// 获取指定文件大小 444 /// </summary> 445 /// <param name="filename"></param> 446 /// <returns></returns> 447 public long GetFileSize(string filename) 448 { 449 FtpWebRequest reqFTP; 450 long fileSize = 0; 451 try 452 { 453 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + filename)); 454 reqFTP.Method = WebRequestMethods.Ftp.GetFileSize; 455 reqFTP.UseBinary = true; 456 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 457 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); 458 Stream ftpStream = response.GetResponseStream(); 459 fileSize = response.ContentLength; 460 461 ftpStream.Close(); 462 response.Close(); 463 } 464 catch (Exception ex) 465 { 466 throw new Exception(ex.Message); 467 } 468 return fileSize; 469 } 470 471 /// <summary> 472 /// 改名 473 /// </summary> 474 /// <param name="currentFilename"></param> 475 /// <param name="newFilename"></param> 476 public void ReName(string currentFilename, string newFilename) 477 { 478 FtpWebRequest reqFTP; 479 try 480 { 481 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + currentFilename)); 482 reqFTP.Method = WebRequestMethods.Ftp.Rename; 483 reqFTP.RenameTo = newFilename; 484 reqFTP.UseBinary = true; 485 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 486 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); 487 Stream ftpStream = response.GetResponseStream(); 488 489 ftpStream.Close(); 490 response.Close(); 491 } 492 catch (Exception ex) 493 { 494 throw new Exception( ex.Message); 495 } 496 } 497 498 /// <summary> 499 /// 移动文件 500 /// </summary> 501 /// <param name="currentFilename"></param> 502 /// <param name="newFilename"></param> 503 public void MovieFile(string currentFilename, string newDirectory) 504 { 505 ReName(currentFilename, newDirectory); 506 } 507 } 508 }
以下是文件信息类(fileinfo),用于各类之间传递。UI上面的数据与fileinfo绑定。在写这个类的时候,我比较偷懒,上传或是下载的更新状态我都放到了fileinfo的DownLoadStatus属性里了,为于避免有道友看不明白,特此说明。
文件信息类:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.ComponentModel; 6 7 namespace WpfApplication1 8 { 9 public class fileInfo:INotifyPropertyChanged 10 { 11 public fileInfo() 12 { 13 complete = 0; 14 } 15 16 //文件名 17 public string fileName { get; set; } 18 //完成进度 19 int _complete; 20 public int complete 21 { 22 get { return _complete; } 23 set 24 { 25 _complete = value; 26 OnPropertyChanged("complete"); 27 } 28 } 29 30 //下载状态 31 string downloadStatus; 32 public string DownLoadStatus 33 { 34 get { return downloadStatus; } 35 set 36 { 37 downloadStatus = value; 38 OnPropertyChanged("DownLoadStatus"); 39 } 40 } 41 42 //本地路径 43 public string LocalPath 44 { get; set; } 45 46 public event PropertyChangedEventHandler PropertyChanged; 47 48 private void OnPropertyChanged(string propertyName) 49 { 50 if (PropertyChanged != null) 51 { 52 PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 53 } 54 } 55 } 56 }
为了进行多线程处理,我封装一个线程信息类,当要取消某个文件下载的时候,可以方便得定位到线程。在这里,我没有采取线程堵塞的方法结束线程,而是在FTP管理类(FTPHelper)里添加了两个标志
//下载取消状态 public bool DownLoadCancelStatus { get { return DownLoadCancel; } } //取消上传状态 public bool UpLoadCancel { get { return _UPLoadCancel; } }
以上两个属性,用于标识是否取消下载或是上传,以上标记为true时,下载或是上传的操作过程即中止,同时触发事件。
线程信息类(DownLoadProcess),命名不太规范,这个类也用于上传文件。
代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 namespace WpfApplication1 8 { 9 public class DownLoadProcess 10 { 11 12 public delegate void DownloadStatusChangeHandle(object sender); 13 public event DownloadStatusChangeHandle OnDownloadStatusChanged; 14 15 public event DownloadStatusChangeHandle OnUpLoadComplete;//上传完成 16 17 FTPHelper FTP; 18 fileInfo file; 19 string Path; 20 Thread downloadThread; 21 Thread uploadThread; 22 23 #region Properties 24 public string DownLoadStatus 25 { get; set; } 26 27 public fileInfo downloadFile 28 { 29 get { return file; } 30 set { file = value; } 31 } 32 33 #endregion 34 35 public DownLoadProcess(FTPHelper f, fileInfo fi,string path) 36 { 37 FTP = f; 38 file = fi; 39 Path = path; 40 FTP.OnDownLoadProgressChanged += new FTPHelper.OnDonwnLoadProcessHandle(FTP_OnDownLoadProgressChanged);//下载 41 FTP.OnUpLoadProgressChanged += new FTPHelper.OnUpLoadProcessHandle(FTP_OnUpLoadProgressChanged);//上传 42 } 43 44 //上传进度 45 void FTP_OnUpLoadProgressChanged(object sender) 46 { 47 FTPHelper ftp = sender as FTPHelper; 48 file.complete = ftp.UpLoadComplete; 49 } 50 51 //下载进度 52 void FTP_OnDownLoadProgressChanged(object sender) 53 { 54 FTPHelper ftp = sender as FTPHelper; 55 file.complete = ftp.DownComplete; 56 } 57 58 //用于线程调用 59 private void ThreadProc() 60 { 61 FTP.Download(Path, file.fileName); 62 if (this.OnDownloadStatusChanged != null&&FTP.DownLoadCancelStatus!=true) 63 { 64 this.DownLoadStatus = "Finished"; 65 OnDownloadStatusChanged(this); 66 } 67 } 68 69 //用于线程调用开始上传 70 private void ThreadUpLoad() 71 { 72 this.file.DownLoadStatus = "上传中..."; 73 FTP.Upload(file.LocalPath); 74 if (FTP.UpLoadCancel != true) 75 { this.file.DownLoadStatus = "完成"; } 76 else 77 { this.file.DownLoadStatus = "已取消"; } 78 Thread.Sleep(300); 79 if (this.OnUpLoadComplete != null) 80 { 81 OnUpLoadComplete(this); 82 } 83 } 84 85 //开始下载 86 public void StartDownLoad() 87 { 88 downloadThread = new Thread(new ThreadStart(this.ThreadProc)); 89 downloadThread.Start(); 90 this.file.DownLoadStatus = "取消"; 91 } 92 93 //开始上传 94 public void StartUpLoad() 95 { 96 uploadThread = new Thread(new ThreadStart(this.ThreadUpLoad)); 97 uploadThread.Start(); 98 } 99 //取消上传 100 public void StopUpLoad() 101 { 102 if (FTP != null) 103 { 104 FTP.CancelUpLoad(); 105 } 106 } 107 108 //取消下载 109 public void StopDownload() 110 { 111 if (FTP != null) 112 { 113 FTP.CancelDownLoad(); 114 115 if (OnDownloadStatusChanged != null) 116 { 117 this.DownLoadStatus = "Canceled"; 118 OnDownloadStatusChanged(this); 119 } 120 } 121 } 122 } 123 }
最后,把界面后台代码贴上来:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Data; 8 using System.Windows.Documents; 9 using System.Windows.Input; 10 using System.Windows.Media; 11 using System.Windows.Media.Imaging; 12 using System.Windows.Navigation; 13 using System.Windows.Shapes; 14 using System.Windows.Forms; 15 using System.Collections.ObjectModel; 16 using System.Threading; 17 using Microsoft.Win32; 18 using System.IO; 19 20 namespace WpfApplication1 21 { 22 23 /// <summary> 24 /// MainWindow.xaml 的交互逻辑 25 /// </summary> 26 public partial class MainWindow : Window 27 { 28 29 ObservableCollection<fileInfo> files = new ObservableCollection<fileInfo>(); 30 List<DownLoadProcess> OnDownLoadList = new List<DownLoadProcess>(); 31 32 public MainWindow() 33 { 34 InitializeComponent(); 35 36 this.fileList.ItemsSource = files; 37 } 38 39 private void Connect_click(object sender, System.Windows.RoutedEventArgs e) 40 { 41 // 在此处添加事件处理程序实现。 42 FTPHelper FTP; 43 FTP = new FTPHelper(this.serverIP.Text, "", this.userID.Text, this.pwd.Password); 44 GetFiles(FTP); 45 46 } 47 48 //获取文件列表 49 private void GetFiles(FTPHelper FTP) 50 { 51 if (FTP != null) 52 { 53 List<string> strFiles = FTP.GetFileList("*"); 54 files.Clear(); 55 for (int i = 0; i < strFiles.Count; i++) 56 { 57 fileInfo f = new fileInfo(); 58 f.fileName = strFiles[i]; 59 f.DownLoadStatus = "下载"; 60 files.Add(f); 61 } 62 } 63 } 64 65 66 private void btn_Click(object sender, RoutedEventArgs e) 67 { 68 69 System.Windows.Controls.Button btn = sender as System.Windows.Controls.Button; 70 fileInfo file = btn.Tag as fileInfo; 71 72 if (file.DownLoadStatus== "下载"||file.DownLoadStatus== "完成") 73 { 74 if (file.DownLoadStatus=="完成") 75 { 76 if (System.Windows.MessageBox.Show("该文件已经下载,是否继续下载?", 77 "提示", MessageBoxButton.YesNo) == MessageBoxResult.No) 78 return; 79 } 80 string path; 81 FolderBrowserDialog dia = new FolderBrowserDialog(); 82 DialogResult result = dia.ShowDialog(); 83 if (result == System.Windows.Forms.DialogResult.Cancel) 84 { return; } 85 path = dia.SelectedPath; 86 87 FTPHelper FTP; 88 FTP = new FTPHelper(this.serverIP.Text, "", this.userID.Text, this.pwd.Password); 89 DownLoadProcess dp = new DownLoadProcess(FTP, file, path); 90 this.OnDownLoadList.Add(dp); 91 dp.StartDownLoad();//开始下载 92 dp.OnDownloadStatusChanged += new DownLoadProcess.DownloadStatusChangeHandle(dp_OnDownloadStatusChanged); 93 94 } 95 //取消下载 96 else 97 { 98 foreach (DownLoadProcess d in OnDownLoadList) 99 { 100 if (d.downloadFile == file) 101 { 102 d.StopDownload(); 103 OnDownLoadList.Remove(d); 104 System.Windows.MessageBox.Show("已取消"); 105 break; 106 } 107 } 108 } 109 110 111 } 112 113 //下载状态发生变化 114 void dp_OnDownloadStatusChanged(object sender) 115 { 116 DownLoadProcess dp = sender as DownLoadProcess; 117 118 if (dp.DownLoadStatus == "Canceled") 119 { 120 dp.downloadFile.complete = 0; 121 dp.downloadFile.DownLoadStatus = "下载"; 122 } 123 else if(dp.DownLoadStatus=="Finished") 124 { 125 dp.downloadFile.DownLoadStatus = "完成"; 126 } 127 } 128 129 //上传文件 130 DownLoadProcess upPro; 131 private void btn_UpLoad(object sender, System.Windows.RoutedEventArgs e) 132 { 133 // 在此处添加事件处理程序实现。 134 if (btnUpload.Content.ToString() == "上传") 135 { 136 btnUpload.Content = "取消"; 137 string filename; 138 System.Windows.Forms.OpenFileDialog opd = new System.Windows.Forms.OpenFileDialog(); 139 DialogResult result = opd.ShowDialog(); 140 if (result == System.Windows.Forms.DialogResult.OK) 141 { 142 filename = opd.FileName; 143 FileInfo fileInf = new FileInfo(filename); 144 fileInfo file = new fileInfo(); 145 file.LocalPath = filename; 146 file.complete = 0; 147 file.fileName = fileInf.Name; 148 gdUpLoad.DataContext = file; 149 FTPHelper FTP; 150 FTP = new FTPHelper(this.serverIP.Text, "", this.userID.Text, this.pwd.Password); 151 upPro = new DownLoadProcess(FTP, file, ""); 152 upPro.OnUpLoadComplete += new DownLoadProcess.DownloadStatusChangeHandle(upPro_OnUpLoadComplete); 153 upPro.StartUpLoad(); 154 filePanel.Visibility = System.Windows.Visibility.Visible; 155 } 156 } 157 else 158 { 159 if (this.upPro != null) 160 { upPro.StopUpLoad(); } 161 } 162 } 163 164 //上传完成 165 void upPro_OnUpLoadComplete(object sender) 166 { 167 UploadCompleteHandle del = new UploadCompleteHandle(UpLoadComplete); 168 this.Dispatcher.BeginInvoke(del); //使用分发器 169 } 170 171 private delegate void UploadCompleteHandle(); 172 private void UpLoadComplete() 173 { 174 this.btnUpload.Content = "上传"; 175 this.filePanel.Visibility = System.Windows.Visibility.Hidden; 176 //把数据源清空 177 gdUpLoad.DataContext = null; 178 FTPHelper FTP; 179 FTP = new FTPHelper(this.serverIP.Text, "", this.userID.Text, this.pwd.Password); 180 GetFiles(FTP); 181 } 182 183 //窗体关闭前,把所有执行中的任务关闭 184 private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 185 { 186 //关闭正在下载中的任务 187 foreach (DownLoadProcess p in OnDownLoadList) 188 { 189 190 } 191 } 192 } 193 194 }
下载管理,我用了一个List进于管理 ,上传的时候,只用了一个线程信息类,还是我比较懒,有些东西,觉得够用就行了,必竟给我工厂里用,已经足够了。至于其他道友要修改的话,也是非常简单的。
使用的开发平台,我用的是VS2010,写代码挺好,就是从界面到代码切换的时候总是会卡住,到网上查了一下,说是VS本身的问题,VS2008倒是没问题,但是没有DataGRid控件,很不爽。所以,我写前台用Blend,后台用VS2010,还好,都是微软件的产品,无缝连接。