分享

多线程下载(FtpWebRequest)-程序开发-红黑联盟

 遥远的桥zz 2011-04-08

网上没找到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"));

摘自红色黑客联盟(www.) 原文:http://www./kf/201007/52824.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约