实现简单的FTP多线程下载和上传

    常想在园子里写点什么东西,但每当提笔,便已觉得肤浅,不敢写出来怡笑大方。对于各位战斗在软件第一线的道友们来说,本人只能算得上是一个业余选手,也许连业余也算不上。始终很自卑,觉得跟大家的水平相差太远。一直以来,对计算机都非常有兴趣,中专毕业以后,通过书籍和网上学了些皮毛。说来惭愧,中专三年,玩了三年游戏,严格地说,只能算是初中毕业。当年的愿望是希望能够从事软件相关的工作,无奈,学历低,专业也不对口。混迹于江湖N年,一直未能如愿。现在在一家工厂里从事管理工作,偶尔写点程序,协助管理。一转眼,毕业十多年了,光阴似箭哪。闲话扯多了,今天,鼓起勇气,写点东西,希望能够得到大家的指导。

  本想找一个相对完整的FTP实现的代码,集成到我工厂的ERP软件里,在网上找了很久,也没有合适的,只好自己动手做一个。以下界面只是测试界面,FTP的管理已经封装成单独的类,可以灵活调用。实现的界面如下图,使用WPF做界面,的确很方便,很灵活。接触WPF真有点相见恨晚的感觉。FTP服务器使用IIS架设,关于如何架设FTP服务器,网上有很多资料,相当简单,在此不多缀述。源码下载:http://files.cnblogs.com/laoyang999/WpfApplication1.zip

实现简单的FTP多线程下载和上传

 

 界面代码如下:

 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管理类

View Code
  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属性里了,为于避免有道友看不明白,特此说明。

文件信息类:

View Code
 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),命名不太规范,这个类也用于上传文件。

代码如下:

View Code
  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 }

最后,把界面后台代码贴上来:

View Code
  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,还好,都是微软件的产品,无缝连接。

你可能感兴趣的:(多线程下载)