private async Task <string> DownloadCoreAsync(ManagedDownload download, Task <Stream> stream, long?length, string contentHash, CancellationToken cancellation) { await this.setupTask.ConfigureAwait(false); Stream writeStream; try { writeStream = await this.storage.GetWriteStreamAsync(download.ContentId, contentHash).ConfigureAwait(false); } catch (Exception ex) { Trace.WriteLine("Error opening write stream: " + ex); download.State = DownloadState.LocalError; return(null); } Stream readStream; try { readStream = await stream.ConfigureAwait(false); } catch (Exception ex) { Trace.WriteLine("Error downloading: " + ex); download.State = DownloadState.DownloadError; return(null); } ConcurrentQueue <(byte[] buffer, int len)> chunks = new (); var errorCancel = new CancellationTokenSource(); Task read = DownloadAsync(chunks, download, readStream, errorCancel, cancellation); Task write = WriteAsync(chunks, length, download, writeStream, errorCancel, cancellation); try { await Task.WhenAll(read, write); } catch (AggregateException aex) { if (aex.InnerException is OperationCanceledException) { return(null); } throw; } try { SHA256 hasher = SHA256.Create(); byte[] hash; using (Stream localReadStream = await this.storage.GetStreamAsync(download.ContentId).ConfigureAwait(false)) hash = hasher.ComputeHash(localReadStream); if (download.State == DownloadState.InProgress) { download.State = DownloadState.Completed; } return(BitConverter.ToString(hash).Replace("-", String.Empty)); } catch (Exception ex) { Trace.WriteLine("Error hashing: " + ex); download.State = DownloadState.LocalError; return(null); } }
public static async Task ImportAsync(IReadOnlyList <IStorageItem> items, IProgress <double> progress = null) { items = GetImportableItems(items); AggregateProgress total = (progress != null) ? new AggregateProgress(progress) : null; ISyncService sync = await App.Services.GetServiceAsync <ISyncService> ().ConfigureAwait(false); DownloadManager downloads = await App.Services.GetServiceAsync <DownloadManager> ().ConfigureAwait(false); List <Task> importTasks = new List <Task> (); foreach (IStorageItem item in items) { var node = total?.CreateProgressNode(); if (item is IStorageFolder folder) { var children = await folder.GetItemsAsync(); importTasks.Add(ImportAsync(children, node)); } else if (item is IStorageFile file) { Task <FileSample> import = null; ManagedDownload download = null; Func <CancellationToken, IProgress <double>, Task <FileSample> > importGetter = async(cancel, progress) => { import = ImportAsync(file, sync, progress, cancel); FileSample sample = null; try { sample = await import; if (download != null) { download.State = DownloadState.Completed; } } catch { if (download != null) { download.State = DownloadState.LocalError; } } return(sample); }; download = downloads.QueueImport(file.Name, importGetter); importTasks.Add(import); } } total?.FinishDiscovery(); await Task.WhenAll(importTasks); }
private async Task <string> DownloadCoreAsync(ManagedDownload download, Uri uri, string contentHash, CancellationToken cancellation) { Task <Stream> stream; long? len; HttpClient client = new HttpClient(); try { HttpResponseMessage result = await client.GetAsync(uri).ConfigureAwait(false); len = result.Content.Headers.ContentLength; stream = result.Content.ReadAsStreamAsync(); } catch (Exception ex) { download.State = DownloadState.DownloadError; Trace.WriteLine("Error downloading: " + ex); return(null); } return(await DownloadCoreAsync(download, stream, len, contentHash, cancellation)); }
public ManagedDownload QueueImport(string name, Func <CancellationToken, IProgress <double>, Task <FileSample> > getImportTask) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException($"'{nameof (name)}' cannot be null or whitespace.", nameof(name)); } if (getImportTask is null) { throw new ArgumentNullException(nameof(getImportTask)); } var source = new CancellationTokenSource(); var download = new ManagedDownload(name); download.Task = SampleToHashTask(getImportTask(source.Token, download)); lock (this.downloads) this.downloads.Add(download); DownloadsChanged?.Invoke(this, EventArgs.Empty); return(download); }
public ManagedDownload QueueDownload(string id, string name, Task <Stream> stream, long length, string contentHash = null, IProgress <double> progress = null, CancellationToken cancellation = default) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException($"'{nameof (name)}' cannot be null or whitespace", nameof(name)); } if (string.IsNullOrWhiteSpace(id)) { throw new ArgumentException($"'{nameof (id)}' cannot be null or whitespace", nameof(id)); } if (stream is null) { throw new ArgumentNullException(nameof(stream)); } var download = new ManagedDownload(id, name); download.Task = DownloadCoreAsync(download, stream, length, contentHash, cancellation); lock (this.downloads) this.downloads.Add(download); DownloadsChanged?.Invoke(this, EventArgs.Empty); return(download); }
public async Task EnsurePresentAsync(FileSample sample, IProgress <double> progress = null, CancellationToken cancellationToken = default) { if (sample is null) { throw new ArgumentNullException(nameof(sample)); } if (await this.storage.GetIsPresentAsync(sample.Id, sample.ContentHash)) { progress?.Report(1); return; } if (!this.settings.DownloadInBackground) { Task <bool> downloadQuestionTask; if (this.downloadInBackground != null) { downloadQuestionTask = this.downloadInBackground; } else { lock (this.settings) { if (this.downloadInBackground == null) { // TODO: Localize var prompt = new PromptMessage("Download missing files", "Some of the files for these elements are missing. Would you like to download them now?", "Download"); Messenger.Default.Send(prompt); this.downloadInBackground = prompt.Result; downloadQuestionTask = this.downloadInBackground; } else { downloadQuestionTask = this.downloadInBackground; } } } if (!await downloadQuestionTask) { progress?.Report(1); return; } } IContentProviderService[] providers = await this.services.GetServicesAsync <IContentProviderService> ().ConfigureAwait(false); IContentProviderService handler = providers.FirstOrDefault(c => c.CanAcquire(sample)); ManagedDownload download = null; if (handler != null) { string id = handler.GetEntryIdFromUrl(sample.SourceUrl); if (id != null) { ContentEntry entry = await handler.GetEntryAsync(id, cancellationToken); download = QueueDownload(sample.Id, sample.Name, handler.DownloadEntryAsync(id), entry.Size, sample.ContentHash, progress, cancellationToken); } } if (download == null) { if (!Uri.TryCreate(sample.SourceUrl, UriKind.Absolute, out Uri uri)) { progress?.Report(1); throw new ArgumentException(); } if (uri.IsFile) { if (await this.storage.GetIsPresentAsync(uri)) { progress?.Report(1); return; } else { progress?.Report(1); throw new FileNotFoundException(); } } download = QueueDownload(sample.Id, sample.Name, new Uri(sample.SourceUrl), sample.ContentHash, progress, cancellationToken); } await download.Task; }