/// <summary> /// Private method that contains the actual logic for adding a download /// </summary> /// <param name="item"></param> private void InternalAddDownload(IDownloadItem item) { // Check dirs if (!Directory.Exists(Config.Instance.GetInProgressDownloadsFolder())) { Directory.CreateDirectory(Config.Instance.GetInProgressDownloadsFolder()); } if (!Directory.Exists(Config.Instance.GetCompleteDownloadsFolder())) { Directory.CreateDirectory(Config.Instance.GetCompleteDownloadsFolder()); } // Create and store downloader IDownloader dl = DownloaderFactory.CreateFrom(item.DownloadUri); dl.SetItem(item); // Register events dl.DownloadProgressChanged += IDownloader_DownloadProgressChanged; dl.DownloadStatusChanged += IDownloader_DownloadStatusChanged; downloads[dl.CurrentDownloadItem] = dl; // Fire event DownloadAdded?.Invoke(this, new DownloadEventArgs(dl.CurrentDownloadItem)); UpdateActiveDownloads(); SaveDownloads(); }
/// <summary> /// Runs all enabled post processors against a <code>DownloadItem</code>, assuming the item has completed /// </summary> /// <param name="item"></param> public void Run(IDownloadItem item) { foreach (var pp in PostProcessors.Where(pp => pp.Enabled || pp.Mandatory).OrderBy(pp => pp.Priority)) { pp.Run(item); } }
public static void StartQueue(string url = null) { if (url != null) { _queueUrl = url; } if (_queueUrl == null) { throw new Exception("DownloadManager:下载队列没有设置Url"); } int num = LoaderMaxCount - _currentLoaderCount; for (int i = 0; i < num; i++) { if (_queue.Count == 0) { break; } IDownloadItem item = _queue.Dequeue(); DownloadItem downloadItem = new DownloadItem(_queueUrl + item.Path, item.Md5, item.Size, AssetLoader.ExternalHotfixPath + "/" + item.Path); downloadItem.Start(OnQueueItemProgress, OnQueueItemError, OnQueueItemLoaded, null); _currentLoaderCount++; } }
/// <summary> /// Given that download items are presently made as a generic DownloadItem from the API POST, this method /// will take that and parse the soulseek data from the DownloadUri /// </summary> /// <param name="item">Any download item with a fake soulseek-like Uri</param> /// <returns>The parsed download information</returns> /// <exception cref="ArgumentException">Thrown when the <paramref name="item"/>does not contain a valid faked soulseek uri</exception> public static SoulseekDownloadItem ParseFrom(IDownloadItem item) { if (item is SoulseekDownloadItem ssItem) { return(ssItem); } return(FakeSoulseekUriBuilder.DeconstructFrom(item)); }
/// <summary> /// Adds a download at the end of the queue. /// </summary> /// <param name="downloadItem">The download to add.</param> public void AddDownload(IDownloadItem downloadItem) { if (_downloadQueue.Any(p => p.RssItem.Guid == downloadItem.RssItem.Guid)) { return; } _downloadQueue.AddLast(downloadItem); RaiseDownloadAdded(new DownloadAddedEventArgs(downloadItem)); }
public async Task StartDownload(string url) { IDownloadItem item = await downloadItemFactory(url); Downloads.Add(item); await item.Start(); if (Downloads.Count > 0) { IsCancelAllEnabled = true; } }
/// <summary> /// Send a download request to the Cache Server. Listen to the DownloadComplete event to read the results. /// </summary> /// <param name="downloadItem">The IDownloadItem that specifies which file to download</param> public void QueueDownload(IDownloadItem downloadItem) { m_stream.Write(Encoding.ASCII.GetBytes(CmdGet + (char)downloadItem.Type), 0, 2); m_stream.Write(downloadItem.Id.guid, 0, GuidLen); m_stream.Write(downloadItem.Id.hash, 0, HashLen); m_downloadQueue.Enqueue(downloadItem); if (m_downloadQueue.Count == 1) { ReadNextDownloadResult(); } }
/// <summary> /// Downloads a file asynchronously. /// </summary> /// <param name="address">The address of the resource to download.</param> /// <param name="filename">The name of the local file that is to receive the data.</param> /// <param name="downloadItem">The download item.</param> /// <param name="token">The token for cancelling the operation.</param> /// <returns>Returns a Task.</returns> private Task <object> DownloadFileAsync( string address, string filename, IDownloadItem downloadItem, CancellationToken token) { var tcs = new TaskCompletionSource <object>(); var webClient = _composer.GetExportedValue <IWebDownloader>(); token.Register(webClient.CancelAsync); webClient.DownloadFileCompleted += (obj, args) => { if (args.Cancelled) { tcs.TrySetCanceled(); downloadItem.DownloadState = DownloadState.Stopped; return; } if (args.Error != null) { tcs.TrySetException(args.Error); downloadItem.DownloadState = DownloadState.Error; return; } tcs.TrySetResult(null); downloadItem.DownloadState = DownloadState.Finished; }; webClient.DownloadProgressChanged += (obj, args) => { downloadItem.ProgressPercentage = args.ProgressPercentage; downloadItem.BytesReceived = args.BytesReceived; downloadItem.TotalBytesToReceive = args.TotalBytesToReceive; }; try { webClient.DownloadFileAsync(new Uri(address), filename); downloadItem.DownloadState = DownloadState.Downloading; } catch (UriFormatException ex) { tcs.TrySetException(ex); } return(tcs.Task); }
public static DownloadItem Load(IDownloadItem downloadItem, string localPath, Action <DownloadItem> onComplete, Action <DownloadItem> onError, Action <float> onProgress, Action <DownloadItem> onCancel = null) { _onComplete = onComplete; _onProgress = onProgress; _onError = onError; _onCancel = onCancel; DownloadItem item = new DownloadItem(downloadItem.Path, downloadItem.Md5, downloadItem.Size, localPath, downloadItem.FileType); item.Start(OnProgress, OnError, OnLoaded, OnCancel); return(item); }
/// <summary> /// Gets the download address. /// </summary> /// <param name="downloadItem">The download item.</param> /// <returns>Returns the URI of the download item.</returns> private string GetDownloadAddress(IDownloadItem downloadItem) { var media = new MediaContent { FileSize = 0 }; foreach (var mediaContent in downloadItem.RssItem.MediaGroup) { if (mediaContent.FileSize > media.FileSize) { media = mediaContent; } } return(media.Url); }
/// <summary> /// Does the opposite of BuildFrom - it takes a faked uri and creates a downloadable item. /// This also copies all of the other properties from the IDownloadItem into the new SoulseekDownloadItem /// </summary> /// <param name="item"></param> /// <returns></returns> public static SoulseekDownloadItem DeconstructFrom(IDownloadItem item) { // Do the thing we're here for var newItem = DeconstructFrom(item.DownloadUri); // Copy all the other properties newItem.CompletedFilename = item.CompletedFilename; newItem.Content = item.Content; newItem.DownloadingFilename = item.DownloadingFilename; newItem.DownloadUri = item.DownloadUri; newItem.Id = item.Id; newItem.Progress = item.Progress; // Return the newly created item return(newItem); }
public void SetItem(IDownloadItem item) { // I keep making this mistake - the ParseFrom method can return a new IDownloadItem, so then referencing `item` after // that references the old one, and so setting the values on that doesn't help anything... CurrentSSDownloadItem = SoulseekDownloadItem.ParseFrom(item); CurrentSSDownloadItem.DownloadingFilename = HttpUtility.UrlDecode(CurrentSSDownloadItem.DownloadUri.Segments.Last()); CurrentSSDownloadItem.CompletedFilename = CurrentSSDownloadItem.DownloadingFilename; CurrentSSDownloadItem.Progress = new DownloadProgress { BytesTotal = 0, BytesDownloaded = 0, Status = DownloadStatus.Pending }; DownloadStatusChanged?.Invoke(this, new DownloadEventArgs(CurrentDownloadItem)); }
protected virtual void SetItem(IDownloadItem item, Uri actualDownloadUri) { CurrentDownloadItem = item; item.DownloadingFilename = HttpUtility.UrlDecode(actualDownloadUri.Segments.Last()); item.CompletedFilename = item.DownloadingFilename; downloader = new PausableEventedDownloader(actualDownloadUri, item.GetDownloadingPath()); downloader.ProgressChanged += Downloader_ProgressChanged; downloader.StatusChanged += Downloader_StatusChanged; downloader.ReceivedResponseFilename += Downloader_ReceivedResponseFilename; item.Progress = new DownloadProgress { BytesTotal = 0, BytesDownloaded = 0, Status = DownloadStatus.Pending }; // Now it's ready, invoke the handler to get download manager to start (or update) DownloadStatusChanged?.Invoke(this, new DownloadEventArgs(CurrentDownloadItem)); }
public void Cancel(IDownloadItem item) => downloads[item].Cancel();
/// <summary> /// Initializes a new instance of the <see cref="DownloadAddedEventArgs"/> class. /// </summary> /// <param name="downloadItem">The added download.</param> public DownloadAddedEventArgs(IDownloadItem downloadItem) { DownloadItem = downloadItem; }
public void Run(IDownloadItem item) { File.Move(item.GetDownloadingPath(), item.GetCompletedPath()); }
/// <summary> /// Gets the download address. /// </summary> /// <param name="downloadItem">The download item.</param> /// <returns>Returns the URI of the download item.</returns> private string GetDownloadAddress(IDownloadItem downloadItem) { var media = new MediaContent { FileSize = 0 }; foreach (var mediaContent in downloadItem.RssItem.MediaGroup) { if (mediaContent.FileSize > media.FileSize) { media = mediaContent; } } return media.Url; }
/// <summary> /// Downloads a file asynchronously. /// </summary> /// <param name="address">The address of the resource to download.</param> /// <param name="filename">The name of the local file that is to receive the data.</param> /// <param name="downloadItem">The download item.</param> /// <param name="token">The token for cancelling the operation.</param> /// <returns>Returns a Task.</returns> private Task<object> DownloadFileAsync( string address, string filename, IDownloadItem downloadItem, CancellationToken token) { var tcs = new TaskCompletionSource<object>(); var webClient = _composer.GetExportedValue<IWebDownloader>(); token.Register(webClient.CancelAsync); webClient.DownloadFileCompleted += (obj, args) => { if (args.Cancelled) { tcs.TrySetCanceled(); downloadItem.DownloadState = DownloadState.Stopped; return; } if (args.Error != null) { tcs.TrySetException(args.Error); downloadItem.DownloadState = DownloadState.Error; return; } tcs.TrySetResult(null); downloadItem.DownloadState = DownloadState.Finished; }; webClient.DownloadProgressChanged += (obj, args) => { downloadItem.ProgressPercentage = args.ProgressPercentage; downloadItem.BytesReceived = args.BytesReceived; downloadItem.TotalBytesToReceive = args.TotalBytesToReceive; }; try { webClient.DownloadFileAsync(new Uri(address), filename); downloadItem.DownloadState = DownloadState.Downloading; } catch (UriFormatException ex) { tcs.TrySetException(ex); } return tcs.Task; }
public virtual void SetItem(IDownloadItem item) => SetItem(item, item.DownloadUri);
public void Resume(IDownloadItem item) => GetExistingDownload(item).Resume();
public void Pause(IDownloadItem item) => GetExistingDownload(item).Pause();
public DownloadProgress GetProgress(IDownloadItem item) => GetExistingDownload(item).CurrentDownloadItem.Progress;
public async override void SetItem(IDownloadItem item) => base.SetItem(item, await GetActualDownloadUri(item.DownloadUri));
/// <summary> /// Removes a <see cref="DownloadItem"/> on the main thread. /// </summary> /// <param name="downloadItem">The download to remove.</param> private void RemoveDownloadItemOnMainThread(IDownloadItem downloadItem) { _mainThreadDispatcher.Invoke(new CollectionInitializerDelegate(p => _downloads.Remove(p)), downloadItem); }
/// <summary> /// Initializes a new instance of the <see cref="DownloadRemovedEventArgs"/> class. /// </summary> /// <param name="downloadItem">The download that has been removed.</param> public DownloadRemovedEventArgs(IDownloadItem downloadItem) { DownloadItem = downloadItem; }
public DownloadEventArgs(IDownloadItem item) => Target = item;
/// <summary> /// Returns the downloader for a specified download item if it exists, otherwise it throws an exception /// </summary> /// <param name="item"></param> /// <returns></returns> private IDownloader GetExistingDownload(IDownloadItem item) => DownloadQueue.Contains(item) ? downloads[item] : throw new KeyNotFoundException();
public void Enqueue(IDownloadItem item) => InternalAddDownload(item);