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