//来自UI的委托 //private UIDelegateContainer uiDelegates; /// <summary> /// 添加任务 /// </summary> /// <param name="plugin">任务所属的插件引用</param> /// <param name="url">任务Url</param> /// <param name="proxySetting">代理服务器设置</param> /// <param name="downSub">下载字幕文件设置</param> /// <returns></returns> public TaskInfo AddTask(IPlugin plugin, string url, WebProxy proxySetting) { //新建TaskInfo对象 TaskInfo task = new TaskInfo(); task.Url = url; task.SourceUrl = url; task.BasePlugin = plugin; object[] types = plugin.GetType().GetCustomAttributes(typeof(AcDownPluginInformationAttribute), true); task.PluginName = (types[0] as AcDownPluginInformationAttribute).Name; task.TaskId = Guid.NewGuid(); task.Proxy = proxySetting; task.CreateTime = DateTime.Now; task.Status = DownloadStatus.等待开始; if (task.SaveDirectory == null) task.SaveDirectory = new DirectoryInfo(CoreManager.ConfigManager.Settings.SavePath); //向集合中添加对象 TaskInfos.Add(task); //提示UI刷新信息 //if (delegates.Refresh != null) // delegates.Refresh.Invoke(new ParaRefresh(task.TaskId)); return task; }
public FormInfo(TaskInfo task) { InitializeComponent(); _task = task; }
/// <summary> /// 下载文件 /// </summary> /// <param name="para">传递的下载参数</param> /// <param name="task">当前下载的任务信息</param> /// <returns>一个布尔值,指示指定的下载是否已成功完成</returns> public static bool DownloadFile(DownloadParameter para, TaskInfo task) { //用于限速的Tick Int32 privateTick = 0; //网络数据包大小 = 1KB byte[] buffer = new byte[1024]; //网络流 Stream st; //文件流 Stream fs; //Deflate/gzip 解压流 Stream decompressStream = null; //缓冲流 BufferedStream bs; //服务器是否支持range bool supportrange = false; //是否启用断点续传 bool enableResume = false; //提取缓存 bool extractcache = false; if (task != null) extractcache = para.ExtractCache; //修正代理服务器 //if (para.Proxy == null) // para.Proxy = new WebProxy(); //初始化重试管理器 bool needRedownload = false; //需要重试下载 int remainRetryTime = GlobalSettings.GetSettings().RetryTimes; //剩余的重试次数 //允许重试时才进行循环 do { //Http请求 HttpWebRequest request; //服务器回应 HttpWebResponse response; #region 获取多次跳转后的真实地址 bool needRedirect = false; //是否需要继续获取Location值(重定向) do { //创建http请求 request = (HttpWebRequest)HttpWebRequest.Create(para.Url); //设置超时 request.Timeout = GlobalSettings.GetSettings().NetworkTimeout; //设置代理服务器 if (para.Proxy != null) request.Proxy = para.Proxy; //设置Cookie if (para.Cookies != null) request.CookieContainer = para.Cookies; request.AllowAutoRedirect = false; //获取服务器回应 response = (HttpWebResponse)request.GetResponse(); if (!string.IsNullOrEmpty(response.Headers["Location"])) { para.Url = response.Headers["Location"]; needRedirect = true; } else { needRedirect = false; } } while (needRedirect); //重新获取服务器回应 #endregion #region 检查文件是否被下载过&是否支持断点续传 //检查服务器是否支持断点续传 if (response != null) supportrange = (response.Headers[HttpResponseHeader.AcceptRanges] == "bytes"); //设置文件长度和已下载的长度 //文件长度 para.TotalLength = response.ContentLength; #region 检查系统缓存 try { if (extractcache && para.TotalLength > 0) //如果允许提取缓存且文件长度大于0时 { //获取temp文件夹 string tempfolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Temp\"); //获取internet cache文件夹 string internettemp = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache); //查找到的文件名称 string filename = null; //查找文件 //internet cache文件夹 string[] files = Directory.GetFiles(internettemp, para.ExtractCachePattern, SearchOption.AllDirectories); foreach (var file in files) { FileInfo fi = new FileInfo(file); if (fi.Length == para.TotalLength) { filename = file; break; } } if (String.IsNullOrEmpty(filename)) //系统temp文件夹 { files = Directory.GetFiles(tempfolder, para.ExtractCachePattern, SearchOption.AllDirectories); foreach (var file in files) { FileInfo fi = new FileInfo(file); if (fi.Length == para.TotalLength) { filename = file; break; } } } //释放空间 files = null; //如果找到文件则直接复制 if (!String.IsNullOrEmpty(filename)) { para.DoneBytes = para.TotalLength; File.Copy(filename, para.FilePath); //不需要继续下载 needRedownload = false; //返回下载成功 return true; } } } catch { //如果复制过程中出错则继续下载 para.DoneBytes = 0; needRedownload = true; } #endregion //建立文件夹 string dir = Directory.GetParent(para.FilePath).ToString(); if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); //如果要下载的文件存在 long filelength = 0; if (File.Exists(para.FilePath)) { filelength = new FileInfo(para.FilePath).Length; if (filelength > 0) { //如果文件长度相同 if (filelength == para.TotalLength) { //返回下载成功 return true; } //如果【已有文件长度小于网络文件总长度】且【服务器支持断点续传】才启用断点续传功能 enableResume = (filelength < para.TotalLength) && supportrange; //如果服务器支持断点续传 if (enableResume) { //重新获取服务器回应 if (response != null) response.Close(); //创建http请求 var newrequest = (HttpWebRequest)HttpWebRequest.Create(para.Url); //设置超时 newrequest.Timeout = GlobalSettings.GetSettings().NetworkTimeout; //设置代理服务器 if (para.Proxy != null) newrequest.Proxy = para.Proxy; //设置Cookie if (para.Cookies != null) request.CookieContainer = para.Cookies; //设置Range newrequest.AddRange(int.Parse(filelength.ToString())); var newresponse = (HttpWebResponse)newrequest.GetResponse(); //检测服务器是否存在欺诈(宣称支持断点续传且返回200 OK,但是内容为报错信息。经常出现在新浪视频服务器的返回信息中) //判定为欺诈的条件为:返回的长度小于剩余(未下载的)文件长度的90% if (newresponse.ContentLength < (para.TotalLength - filelength) * 9 / 10) { //重新获取文件 response = (HttpWebResponse)request.GetResponse(); //服务器不支持断点续传 enableResume = false; //设置"已完成字节数" para.DoneBytes = 0; } else { //服务器支持断点续传 para.DoneBytes = filelength; //设置新连接 response = newresponse; } } } } #endregion int t, limitcount = 0; //系统计数 para.LastTick = System.Environment.TickCount; //获取下载流 using (st = response.GetResponseStream()) { //设置gzip/deflate解压缩 if (response.ContentEncoding == "gzip") { decompressStream = new GZipStream(st, CompressionMode.Decompress); } else if (response.ContentEncoding == "deflate") { decompressStream = new DeflateStream(st, CompressionMode.Decompress); } else { decompressStream = st; } //设置FileStream if (enableResume)//若允许断点续传 { fs = new FileStream(para.FilePath, FileMode.Open, FileAccess.Write, FileShare.Read, 8); fs.Seek(filelength, SeekOrigin.Begin); } else //不允许断点续传 { fs = new FileStream(para.FilePath, FileMode.Create, FileAccess.Write, FileShare.Read, 8); } //打开文件流 using (fs) { //使用缓冲流 bs = new BufferedStream(fs, GlobalSettings.GetSettings().CacheSize * 1024 * 1024); try { //读取第一块数据 Int32 osize = decompressStream.Read(buffer, 0, buffer.Length); //开始循环 while (osize > 0) { #region 判断是否取消下载 //如果用户终止则返回false if (para.IsStop) { //关闭流 bs.Close(); st.Close(); fs.Close(); return false; } #endregion //增加已完成字节数 para.DoneBytes += osize; //写文件(缓存) bs.Write(buffer, 0, osize); //设置限速 int limit = 0; if (task != null) if (task.SpeedLimit >= 0) limit = task.SpeedLimit; if (limit > 0) { //下载计数加一count++ limitcount++; //下载1KB osize = decompressStream.Read(buffer, 0, buffer.Length); //累积到limit KB后 if (limitcount >= limit) { t = System.Environment.TickCount - privateTick; //检查是否大于一秒 if (t < 1000) //如果小于一秒则等待至一秒 Thread.Sleep(1000 - t); //重置count和计时器,继续下载 limitcount = 0; privateTick = System.Environment.TickCount; } } else //如果不限速 { osize = decompressStream.Read(buffer, 0, buffer.Length); } } //end while //如果下载完成的数据没有到达服务器宣称的长度的90%就报告错误 if (para.TotalLength > 0) if (para.DoneBytes < (para.TotalLength * 9 / 10)) throw new Exception("Data downloaded is less than the server announced."); //下载成功完成,不需要重新下载 needRedownload = false; } //end bufferedstream catch (Exception ex) { //可重试次数减1 remainRetryTime--; //不再重试直接抛出异常的规则: //1.没有可重试次数 //2.服务器不支持断点续传 if (remainRetryTime < 0 || (!enableResume)) { needRedownload = false; throw ex; } else //否则继续重试 { needRedownload = true; //重试前等待的时间 Thread.Sleep(GlobalSettings.GetSettings().RetryWaitingTime); } } finally { bs.Close(); } }// end filestream } //end netstream } while (needRedownload); //end while(needReDownload) //一切顺利返回true return true; }
/// <summary> /// 下载文件 /// </summary> /// <param name="para">传递的下载参数</param> /// <param name="task">当前下载的任务信息</param> /// <returns>一个布尔值,指示指定的下载是否已成功完成</returns> public static bool DownloadFile(DownloadParameter para, TaskInfo task) { //用于限速的Tick Int32 privateTick = 0; //网络数据包大小 = 1KB byte[] buffer = new byte[1024]; //网络流 Stream st; //文件流 Stream fs; //Deflate/gzip 解压流 Stream decompressStream = null; //缓冲流 BufferedStream bs; //服务器是否支持range bool supportrange = false; //是否启用断点续传 bool enableResume = false; //提取缓存 bool extractcache = false; if (task != null) { extractcache = para.ExtractCache; } //修正代理服务器 //if (para.Proxy == null) // para.Proxy = new WebProxy(); //初始化重试管理器 bool needRedownload = false; //需要重试下载 int remainRetryTime = GlobalSettings.GetSettings().RetryTimes; //剩余的重试次数 //允许重试时才进行循环 do { //Http请求 HttpWebRequest request; //服务器回应 HttpWebResponse response; #region 获取多次跳转后的真实地址 bool needRedirect = false; //是否需要继续获取Location值(重定向) do { //创建http请求 request = (HttpWebRequest)HttpWebRequest.Create(new Uri(para.Url)); //设置超时 request.Timeout = GlobalSettings.GetSettings().NetworkTimeout; //设置代理服务器 //if (para.Proxy != null) [WorkItem #1448] request.Proxy = para.Proxy; //设置Cookie if (para.Cookies != null) { request.CookieContainer = para.Cookies; } request.AllowAutoRedirect = false; //设置Referer和UA request.Referer = para.Referer; request.UserAgent = para.UserAgent; //获取服务器回应 response = (HttpWebResponse)request.GetResponse(); if (!string.IsNullOrEmpty(response.Headers["Location"])) { para.Url = response.Headers["Location"]; needRedirect = true; } else { needRedirect = false; } } while (needRedirect); //重新获取服务器回应 #endregion #region 检查文件是否被下载过&是否支持断点续传 //检查服务器是否支持断点续传 if (response != null) { supportrange = (response.Headers[HttpResponseHeader.AcceptRanges] == "bytes"); } //设置文件长度和已下载的长度 //文件长度 para.TotalLength = response.ContentLength; #region 检查系统缓存 try { if (extractcache && para.TotalLength > 0) //如果允许提取缓存且文件长度大于0时 { //获取temp文件夹 string tempfolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Temp\"); //获取internet cache文件夹 string internettemp = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache); //查找到的文件名称 string filename = null; //查找文件 //internet cache文件夹 string[] files = Directory.GetFiles(internettemp, para.ExtractCachePattern, SearchOption.AllDirectories); foreach (var file in files) { FileInfo fi = new FileInfo(file); if (fi.Length == para.TotalLength) { filename = file; break; } } if (String.IsNullOrEmpty(filename)) //系统temp文件夹 { files = Directory.GetFiles(tempfolder, para.ExtractCachePattern, SearchOption.AllDirectories); foreach (var file in files) { FileInfo fi = new FileInfo(file); if (fi.Length == para.TotalLength) { filename = file; break; } } } //释放空间 files = null; //如果找到文件则直接复制 if (!String.IsNullOrEmpty(filename)) { para.DoneBytes = para.TotalLength; File.Copy(filename, para.FilePath); //不需要继续下载 needRedownload = false; //返回下载成功 return(true); } } } catch { //如果复制过程中出错则继续下载 para.DoneBytes = 0; needRedownload = true; } #endregion //建立文件夹 string dir = Directory.GetParent(para.FilePath).ToString(); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } //如果要下载的文件存在 long filelength = 0; if (File.Exists(para.FilePath)) { filelength = new FileInfo(para.FilePath).Length; if (filelength > 0) { //如果文件长度相同 if (filelength == para.TotalLength) { //返回下载成功 return(true); } //如果【已有文件长度小于网络文件总长度】且【服务器支持断点续传】才启用断点续传功能 enableResume = (filelength < para.TotalLength) && supportrange; //如果服务器支持断点续传 if (enableResume) { //重新获取服务器回应 if (response != null) { response.Close(); } //创建http请求 var newrequest = (HttpWebRequest)HttpWebRequest.Create(para.Url); //设置超时 newrequest.Timeout = GlobalSettings.GetSettings().NetworkTimeout; //设置代理服务器 //if (para.Proxy != null) [WorkItem #1448] newrequest.Proxy = para.Proxy; //设置Cookie if (para.Cookies != null) { newrequest.CookieContainer = para.Cookies; } //设置Range newrequest.AddRange(int.Parse(filelength.ToString())); //设置Referer和UA newrequest.Referer = para.Referer; newrequest.UserAgent = para.UserAgent; var newresponse = (HttpWebResponse)newrequest.GetResponse(); //检测服务器是否存在欺诈(宣称支持断点续传且返回200 OK,但是内容为报错信息。经常出现在新浪视频服务器的返回信息中) //判定为欺诈的条件为:返回的长度小于剩余(未下载的)文件长度的90% if (newresponse.ContentLength < (para.TotalLength - filelength) * 9 / 10) { //重新获取文件 response = (HttpWebResponse)request.GetResponse(); //服务器不支持断点续传 enableResume = false; //设置"已完成字节数" para.DoneBytes = 0; } else { //服务器支持断点续传 para.DoneBytes = filelength; //设置新连接 response = newresponse; } } } } #endregion int t, limitcount = 0; //系统计数 para.LastTick = System.Environment.TickCount; //获取下载流 using (st = response.GetResponseStream()) { //设置gzip/deflate解压缩 if (response.ContentEncoding == "gzip") { decompressStream = new GZipStream(st, CompressionMode.Decompress); } else if (response.ContentEncoding == "deflate") { decompressStream = new DeflateStream(st, CompressionMode.Decompress); } else { decompressStream = st; } //设置FileStream if (enableResume) //若允许断点续传 { fs = new FileStream(para.FilePath, FileMode.Open, FileAccess.Write, FileShare.Read, 8); fs.Seek(filelength, SeekOrigin.Begin); } else //不允许断点续传 { fs = new FileStream(para.FilePath, FileMode.Create, FileAccess.Write, FileShare.Read, 8); } //打开文件流 using (fs) { //使用缓冲流 bs = new BufferedStream(fs, GlobalSettings.GetSettings().CacheSize * 1024 * 1024); try { //读取第一块数据 Int32 osize = decompressStream.Read(buffer, 0, buffer.Length); //开始循环 while (osize > 0) { #region 判断是否取消下载 //如果用户终止则返回false if (para.IsStop) { //关闭流 bs.Close(); st.Close(); fs.Close(); return(false); } #endregion //增加已完成字节数 para.DoneBytes += osize; //写文件(缓存) bs.Write(buffer, 0, osize); //设置限速 int limit = 0; if (task != null) { if (task.SpeedLimit >= 0) { limit = task.SpeedLimit; } } if (limit > 0) { //下载计数加一count++ limitcount++; //下载1KB osize = decompressStream.Read(buffer, 0, buffer.Length); //累积到limit KB后 if (limitcount >= limit) { t = System.Environment.TickCount - privateTick; //检查是否大于一秒 if (t < 1000) //如果小于一秒则等待至一秒 { Thread.Sleep(1000 - t); } //重置count和计时器,继续下载 limitcount = 0; privateTick = System.Environment.TickCount; } } else //如果不限速 { osize = decompressStream.Read(buffer, 0, buffer.Length); } } //end while //如果下载完成的数据没有到达服务器宣称的长度的90%就报告错误 if (para.TotalLength > 0) { if (para.DoneBytes < (para.TotalLength * 9 / 10)) { throw new Exception("Data downloaded is less than the server announced."); } } //下载成功完成,不需要重新下载 needRedownload = false; } //end bufferedstream catch (Exception ex) { //可重试次数减1 remainRetryTime--; //不再重试直接抛出异常的规则: //1.没有可重试次数 //2.服务器不支持断点续传 if (remainRetryTime < 0 || (!enableResume)) { needRedownload = false; throw ex; } else //否则继续重试 { needRedownload = true; //重试前等待的时间 Thread.Sleep(GlobalSettings.GetSettings().RetryWaitingTime); } } finally { bs.Close(); } } // end filestream } //end netstream } while (needRedownload); //end while(needReDownload) //一切顺利返回true return(true); }
/// <summary> /// 删除任务(自动终止未停止的任务) /// </summary> /// <param name="task"></param> public void DeleteTask(TaskInfo task, bool deleteFile, bool removeToRecyclebin) { //停止任务 StopTask(task); //启动新线程等待任务完全停止 ThreadPool.QueueUserWorkItem(new WaitCallback((o) => { while (task.Status == DownloadStatus.正在停止 || task.Status == DownloadStatus.正在下载) { Thread.Sleep(50); } //是否删除文件 if (deleteFile) { //删除所有视频文件 foreach (var f in task.FilePath) { if (File.Exists(f)) { try { File.Delete(f); } catch (Exception ex) { Logging.Add(ex); } } } //删除所有字幕文件 foreach (var item in task.SubFilePath) { if (File.Exists(item)) { try { File.Delete(item); } catch (Exception ex) { Logging.Add(ex); } } } //检查视频文件所在文件夹,如果文件夹中是空的,那么就删除这个文件夹 if (task.FilePath.Count > 0) { var dir = Path.GetDirectoryName(task.FilePath[0]); try { Directory.Delete(dir, false); } catch (Exception ex) { Logging.Add(ex); } } } //从任务列表中删除任务 if (task.Status != DownloadStatus.已删除 && removeToRecyclebin) { //移动到回收站 task.Status = DownloadStatus.已删除; } else //如果任务已经删除至回收站 { //移除集合中的任务 TaskInfos.Remove(task); } //刷新信息 preDelegates.Refresh(new ParaRefresh(task)); })); }
/// <summary> /// 停止任务 /// </summary> /// <param name="task"></param> public void StopTask(TaskInfo task) { //只有已开始的任务才可停止 switch (task.Status) { case DownloadStatus.等待开始: //尚未开始的任务直接停止 task.Status = DownloadStatus.已经停止; break; case DownloadStatus.正在下载: //已经开始的任务启动新线程停止 task.Status = DownloadStatus.正在停止; break; default: return; } //刷新信息 preDelegates.Refresh(new ParaRefresh(task)); //停止任务 task.Stop(); if (task.Status != DownloadStatus.已经停止) { //启动新线程等待任务完全停止 Thread t = new Thread(new ThreadStart(() => { //超时时长 (10秒钟) int timeout = 10000; //等待停止 while (task.Status == DownloadStatus.正在停止) { Thread.Sleep(500); timeout -= 500; if (timeout < 0) //如果到时仍未停止 { task.Status = DownloadStatus.已经停止; break; } } //刷新信息 preDelegates.Refresh(new ParaRefresh(task)); })); t.IsBackground = true; t.Start(); } //销毁Downloader task.DisposeDownloader(); }
public ParaRefresh(TaskInfo task) { SourceTask = task; }
public ParaNewTask(IPlugin plugin, string url, TaskInfo sourceTask) { Plugin = plugin; Url = url; SourceTask = sourceTask; }
public ParaFinish(TaskInfo task, bool isSuccess) { SourceTask = task; Successed = isSuccess; }
public ParaTipText(TaskInfo task, string tip) { SourceTask = task; TipText = tip; }
public ParaNewPart(TaskInfo task, Int32 partNum) { SourceTask = task; PartNumber = partNum; }
/// <summary> /// 删除任务(自动终止未停止的任务) /// </summary> /// <param name="task"></param> public void DeleteTask(TaskInfo task, bool deleteFile, bool removeToRecyclebin) { //停止任务 StopTask(task); //启动新线程等待任务完全停止 Thread t = new Thread(new ThreadStart(() => { while (task.Status == DownloadStatus.正在停止 || task.Status == DownloadStatus.正在下载) { Thread.Sleep(50); } //是否删除文件 if (deleteFile) { //删除所有视频文件 foreach (var f in task.FilePath) { if (File.Exists(f)) { try { File.Delete(f); } catch (Exception ex) { Logging.Add(ex); } } } //删除所有字幕文件 foreach (var item in task.SubFilePath) { if (File.Exists(item)) { try { File.Delete(item); } catch (Exception ex) { Logging.Add(ex); } } } } //从任务列表中删除任务 if (task.Status != DownloadStatus.已删除 && removeToRecyclebin) { //移动到回收站 task.Status = DownloadStatus.已删除; } else //如果任务已经删除至回收站 { //移除集合中的任务 TaskInfos.Remove(task); } //刷新信息 preDelegates.Refresh(new ParaRefresh(task)); })); t.IsBackground = true; t.Start(); }
public ParaError(TaskInfo task, Exception excp) { SourceTask = task; E = excp; }
/// <summary> /// 开始任务 /// </summary> public void StartTask(TaskInfo task) { //如果正在停止则什么都不做(等待任务正常停止) if (task.Status == DownloadStatus.正在停止 || task.Status == DownloadStatus.正在下载) return; //如果队列未满则开始下载 if (GetRunningCount() < CoreManager.ConfigManager.Settings.MaxRunningTaskCount) { //启动新线程下载文件 Thread t = new Thread(() => { try { //AcDown规范:仅有TaskManager及插件本身有权修改其所属TaskInfo对象的Status属性 task.Status = DownloadStatus.正在下载; preDelegates.Start(new ParaStart(task)); //下载视频 bool finished = task.Start(preDelegates); if (finished) { //设置完成状态 if (task.PartialFinished) task.Status = DownloadStatus.部分完成; else task.Status = DownloadStatus.下载完成; } else { task.Status = DownloadStatus.已经停止; } preDelegates.Finish(new ParaFinish(task, finished)); } catch (Exception ex) //如果出现错误 { task.Status = DownloadStatus.出现错误; preDelegates.Error(new ParaError(task, ex)); } }); t.IsBackground = true; //开始下载 t.Start(); } else //如果队列已满,则转换状态至“等待开始” { task.Status = DownloadStatus.等待开始; } //刷新UI preDelegates.Refresh(new ParaRefresh(task)); }
public ParaStart(TaskInfo task) { SourceTask = task; }
/// <summary> /// 判断所提供的任务是否符合当前过滤器 /// </summary> private bool IsMatchCurrentFilter(TaskInfo task) { string tmp = task.ToString(); foreach (string f in _filter) { if (f.Trim() != "") if (tmp.IndexOf(f.Trim(), StringComparison.CurrentCultureIgnoreCase) >= 0) return true; } return false; }