多线程下载(FtpWebRequest)

网上没找到FtpWebRequest多线程下载的资料,自己写了一个。但没达到预期效果,下面是测试结果:

//1线程下载133M 18秒
//5线程 下载133M 40秒

//单线程 下载133M 12秒

期望高手不吝赐教,下面是完整代码

首先命名空间

 

using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Net;

 

 

类主体:

 

代码
    public class MultiFtpService
    {
        
#region 变量

        
private string _Server;//服务器地址
        private string _UserName;//用户名
        private string _Password;//密码
        private int _Port;//端口
        private long _FileSize;//文件大小
        private string _FileUrl;//文件地址
        private string _SavePath;//保存路经        
        private string _SaveFileName;//保存文件名
        private string _SaveExtName;//保存文件扩展名
        private int _ThreadNum;//线程数量
        private short _ThreadCompleteNum;//线程完成数量
        private bool _IsComplete = false;//是否完成
        private volatile int _DownloadSize;//当前下载大小
        private Thread[] _Thread;//线程数组
        private List<string> _TempFiles = new List<string>();
        
private FtpWebRequest ftpRequest;

        
#endregion

        
#region 属性

        
public string Server
        {
            
get { return _Server; }
            
set { _Server = value; }
        }

        
public string UserName
        {
            
get { return _UserName; }
            
set { _UserName = value; }
        }

        
public string Password
        {
            
get { return _Password; }
            
set { _Password = value; }
        }

        
public int Port
        {
            
get { return _Port; }
            
set { _Port = value; }
        }

        
public long FileSize
        {
            
get { return _FileSize; }
            
set { _FileSize = value; }
        }

        
public string FileUrl
        {
            
get { return _FileUrl; }
            
set { _FileUrl = value; }
        }

        
public string SavePath
        {
            
get { return _SavePath; }
            
set { _SavePath = value; }
        }

        
public string SaveFileName
        {
            
get { return _SaveFileName; }
            
set { _SaveFileName = value; }
        }

        
public string SaveExtName
        {
            
get { return _SaveExtName; }
            
set { _SaveExtName = value; }
        }

        
public int ThreadNum
        {
            
get { return _ThreadNum; }
            
set { _ThreadNum = value; }
        }

        
public short ThreadCompleteNum
        {
            
get { return _ThreadCompleteNum; }
            
set { _ThreadCompleteNum = value; }
        }

        
public bool IsComplete
        {
            
get { return _IsComplete; }
        }

        
public int DownloadSize
        {
            
get { return _DownloadSize; }
        }

        
#endregion

        
#region Constructor

        
public MultiFtpService(string server, string username, string password, int threadNum)
            : 
this(server, username, password, 21, threadNum, """")
        {
        }

        
public MultiFtpService(string server, string username, string password, int port,int threadNum)
            : 
this(server, username, password, port, threadNum, """")
        {
        }

        
public MultiFtpService(string server, string username, string password, int threadNum, string fileUrl, string savePath)
            : 
this(server, username, password, 21, threadNum, fileUrl, savePath)
        {
        }

        
public MultiFtpService(string server, string username, string password, int port,int threadNum, string fileUrl, string savePath)
        {
            _Server 
= server;
            _UserName 
= username;
            _Password 
= password;
            _Port 
= port;
            _ThreadNum 
= threadNum;
            _FileUrl 
= fileUrl;
            _SavePath 
= savePath;
            _Thread 
= new Thread[_ThreadNum];
        }

        
#endregion

        
#region Functions

        
public void Start()
        {
            FtpWebRequest ftpRequest 
= (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + _Server + ":" + _Port + "/" + _FileUrl));
            ftpRequest.Method 
= WebRequestMethods.Ftp.GetFileSize;
            ftpRequest.KeepAlive 
= false;
            ftpRequest.UseBinary 
= true;
            ftpRequest.Credentials 
= new NetworkCredential(_UserName, _Password);
            FtpWebResponse response 
= (FtpWebResponse)ftpRequest.GetResponse();
            _FileSize 
= response.ContentLength;
            
int singelNum = (int)(_FileSize / _ThreadNum);//平均分配
            int remainder = (int)(_FileSize % _ThreadNum);//获取剩余的
            for (int i = 0; i < _ThreadNum; i++)
            {
                List
<int> range = new List<int>();
                range.Add(i 
* singelNum);
                
if (remainder != 0 && (_ThreadNum - 1== i)//剩余的交给最后一个线程
                    range.Add(i * singelNum + singelNum + remainder - 1);
                
else
                    range.Add(i 
* singelNum + singelNum - 1);
                _Thread[i] 
= new Thread(() => { Download(range[0], range[1]); });
                _Thread[i].Name 
= string.Format("thread_{0}",i + 1);
                _Thread[i].Start();
            }
        }

        
/// <summary>
        
/// 拆分分段下载
        
/// </summary>
        
/// <param name="from">开始</param>
        
/// <param name="to">结束</param>
        private void Download(int from, int to)
        {
            
string tmpFileBlock = string.Format(@"{0}\{1}_{2}.dat", _SavePath, _SaveFileName, Thread.CurrentThread.Name);
            _TempFiles.Add(tmpFileBlock);
            
int count = 0;
            
int readCount = 0;
            
try
            {
                ftpRequest 
= (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + _Server + ":" + _Port + "/" + _FileUrl));
                
//ftpRequest.ContentOffset = from;//设置文件的偏移量
                ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile;
                ftpRequest.UseBinary 
= true;
                ftpRequest.Credentials 
= new NetworkCredential(UserName, Password);
                
using (FileStream outputStream = new FileStream(tmpFileBlock, FileMode.Create))
                
using (FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse())
                
using (Stream ftpStream = response.GetResponseStream())
                {
                    
int bufferSize = 81920;
                    
byte[] buffer = new byte[bufferSize];

                    
while ((readCount = ftpStream.Read(buffer, 0, bufferSize)) > 0)
                    {
                        count 
+= readCount;
                        
if (from<to && from + readCount >= to)
                        {
                            outputStream.Write(buffer, 
0, to-from);
                            _DownloadSize 
+= to - from;
                            
break;
                        }
                        
else if (from == count - readCount)
                        {
                            outputStream.Write(buffer, 
0, readCount);
                            _DownloadSize 
+= readCount;
                            from 
= count;
                        }
                        
else if (count > from && from > count - readCount)
                        {
                            outputStream.Write(buffer, readCount 
- (count - from), count - from);
                            _DownloadSize 
+= count - from;
                            from 
= count;
                        }
                    }
                    _ThreadCompleteNum
++;
                }
            }
            
catch (Exception e)
            {
                
throw e;
            }
            
if (_ThreadCompleteNum == _ThreadNum)
            {
                Complete();
            }
        }

        
/// <summary>
        
/// 合并临时文件
        
/// </summary>
        private void Complete()
        {
            Stream mergeFile 
= new FileStream(string.Format(@"{0}\{1}{2}",_SavePath,_SaveFileName,_SaveExtName), FileMode.Create);
            BinaryWriter AddWriter 
= new BinaryWriter(mergeFile);
            
foreach (string file in _TempFiles)
            {
                
using (FileStream fs = new FileStream(file, FileMode.Open))
                
using(BinaryReader tempReader = new BinaryReader(fs))
                {
                    AddWriter.Write(tempReader.ReadBytes((
int)fs.Length));
                }
                File.Delete(file);
            }
            AddWriter.Close();
            _IsComplete 
= true;
        }

        
#endregion
    }

 

 

测试代码:

 

代码
MultiFtpService multiFtp = new MultiFtpService("172.18.118.106""ff""ff",1);
string path = "10031544820/20100310/4014200";
            DateTime dt 
= DateTime.Now;
            
string fileName = "CX.IMG";
            
//ftp.Download(path + "/" + fileName, pathdir + "/" + path + "/" + fileName, true);
            multiFtp.FileUrl = path + "/" + fileName;
            multiFtp.SavePath 
= pathdir + "/" + path;
            multiFtp.SaveFileName 
= fileName.Substring(0, fileName.IndexOf('.'));
            multiFtp.SaveExtName 
= fileName.Substring(fileName.IndexOf('.'));
            multiFtp.Start();
            
while (!multiFtp.IsComplete)
            {
                System.Threading.Thread.Sleep(
1);
            }
            MessageBox.Show(
"完成:前时间为" + dt.ToString("yyyy-MM-dd hh:mm:ss"+ "\n" + "现在时间为" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));

 

 

posted @ 2010-04-21 18:04  nyzfl  阅读(4110)  评论(5编辑  收藏  举报