public static void UpdateDownloadableLanguagesInfo(string ocrLanguagesManifestFileLocalPath, CompletionDelegate completion) { DownloadableLanguagesError = null; List <Task> downloadTasks = new List <Task>(); Task task = Task.Run(async() => { string[] directories = { LanguagesDirectory }; void ParseManifestJsonText(string jsonContent) { _originalDeserializedManifest = JsonConvert.DeserializeObject <Dictionary <string, object> >(jsonContent); if (_originalDeserializedManifest != null) { Manifest = new Dictionary <string, Dictionary <string, Dictionary <string, object> > >(_originalDeserializedManifest.Count); } foreach (KeyValuePair <string, object> entry in _originalDeserializedManifest) { if (entry.Value.GetType() != typeof(string)) { // Not the "Version" tag Dictionary <string, Dictionary <string, object> > val = (JToken.FromObject(entry.Value)).ToObject(typeof(Dictionary <string, Dictionary <string, object> >)) as Dictionary <string, Dictionary <string, object> >; Manifest.Add(entry.Key, val); } } DownloadableLanguagesError = Manifest != null ? null : new Exception("Error parsing OCR languages manifest file"); if (Manifest == null) { Manifest = GenerateTemporaryManifestWithLanguageFilesInDirectories(directories); } UpdateLanguagesWithCurrentManifest(); completion?.Invoke(null, DownloadableLanguagesError); } if (!string.IsNullOrWhiteSpace(ocrLanguagesManifestFileLocalPath)) { // Read from the embedded resource using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ocrLanguagesManifestFileLocalPath)) using (StreamReader reader = new StreamReader(stream)) { string jsonContent = reader.ReadToEnd(); ParseManifestJsonText(jsonContent); } } else if (AdditionalLanguagesURL != null) { string url = Path.Combine(AdditionalLanguagesURL, "Manifest.json"); string fileDownloadLocation = Path.Combine(_downloadLanguagesDirectory, Path.GetFileName(url)); HttpClientDownloader httpClientDownloader = new HttpClientDownloader(); httpClientDownloader.DownloadCompleted += (object sender, DownloadCompletedEventArgs e) => { if (!string.IsNullOrWhiteSpace(fileDownloadLocation) && File.Exists(fileDownloadLocation)) { string jsonContent = File.ReadAllText(fileDownloadLocation); ParseManifestJsonText(jsonContent); } else { Manifest = null; DownloadableLanguagesError = e.Error; } }; try { await httpClientDownloader.DownloadFileAsync(url, fileDownloadLocation, null); } catch (Exception ex) { Console.WriteLine(ex.Message); } } else { Manifest = GenerateTemporaryManifestWithLanguageFilesInDirectories(directories); } }); if (!string.IsNullOrWhiteSpace(ocrLanguagesManifestFileLocalPath)) { downloadTasks.Add(task); Task.WaitAll(downloadTasks.ToArray(), -1); } }
private static void DownloadLanguageFiles(Dictionary <string, string> urls, string language, ProgressDelegate progress, CompletionDelegate completion) { OcrLanguage currentlyDownloadingLanguage = null; List <Exception> downloadErrors = new List <Exception>(); bool cancelled = false; try { if (urls.Count == 0) { var downloadableLanguages = DownloadableLanguages.Where(l => l.Language.Equals(language)); if (downloadableLanguages.Count() > 0) { currentlyDownloadingLanguage = downloadableLanguages.ElementAt(0); } completion?.Invoke(currentlyDownloadingLanguage, null); return; } currentlyDownloadingLanguage = GetCurrentlyDownloadingLanguage(urls.Values.ElementAt(0)); if (currentlyDownloadingLanguage != null) { if (currentlyDownloadingLanguage.CancellationTokenSource != null) { currentlyDownloadingLanguage.CancellationTokenSource.Dispose(); currentlyDownloadingLanguage.CancellationTokenSource = null; } currentlyDownloadingLanguage.CancellationTokenSource = new CancellationTokenSource(); currentlyDownloadingLanguage.IsDownloading = true; } long totalSizeToDownload = 0; Task task = null; Dictionary <string, long> totalBytesReceivedForAllDownloads = new Dictionary <string, long>(); List <Task> downloadTasks = new List <Task>(); HttpClientDownloader httpClientDownloader = new HttpClientDownloader(); httpClientDownloader.DownloadCompleted += (object sender, DownloadCompletedEventArgs e) => { if (!e.Cancelled && e.Error == null) { string finalPath = Path.Combine(LanguagesDirectory, Path.GetFileName(e.TargetFilePath)); MoveFile(e.TargetFilePath, finalPath); } else if (e.Cancelled) { cancelled = true; } else if (e.Error != null) { downloadErrors.Add(e.Error); } if (cancelled || e.Error != null) { // Delete temporary file in case or cancellation or error. DeleteFile(e.TargetFilePath); } }; httpClientDownloader.DownloadProgressChanged += (object sender, DownloadProgressChangedEventArgs e) => { // if error occurred while downloading any of this language files, then abort the rest. if (downloadErrors.Count > 0) { CancelDownloadForLanguage(currentlyDownloadingLanguage.Language); return; } if (currentlyDownloadingLanguage != null) { if (!currentlyDownloadingLanguage.IsDownloading) { // User cancelled the download of this language return; } long totalBytesReceived = 0; lock (totalBytesReceivedForAllDownloads) { totalBytesReceivedForAllDownloads[e.SourceFileUrl] = e.BytesReceived; foreach (KeyValuePair <string, long> entry in totalBytesReceivedForAllDownloads) { totalBytesReceived += entry.Value; } } currentlyDownloadingLanguage.DownloadPercentage = Math.Round((double)totalBytesReceived / totalSizeToDownload * 100, 2); progress?.Invoke(currentlyDownloadingLanguage, currentlyDownloadingLanguage.DownloadPercentage); } }; void StartDownloadTask(string url) { try { if (downloadErrors.Count > 0) { return; } string targetFilePath = Path.Combine(_downloadLanguagesDirectory, Path.GetFileName(url)); task = httpClientDownloader.DownloadFileAsync(url, targetFilePath, currentlyDownloadingLanguage.CancellationTokenSource?.Token); downloadTasks.Add(task); } catch (Exception ex2) { Console.WriteLine(ex2.Message); } } foreach (KeyValuePair <string, string> entry in urls) { string url = entry.Value; string languageFile = Path.GetFileName(url); string identifier = languageFile.Split('.')[1]; object sizeValue = Manifest[identifier][languageFile][FileSizeKeyString]; if (sizeValue.GetType() == typeof(long)) { totalSizeToDownload += (long)sizeValue; } StartDownloadTask(url); } Task.WaitAll(downloadTasks.ToArray(), -1, (currentlyDownloadingLanguage.CancellationTokenSource != null) ? currentlyDownloadingLanguage.CancellationTokenSource.Token : CancellationToken.None); downloadTasks.Clear(); if (!cancelled) { DownloadableLanguages.Remove(currentlyDownloadingLanguage); LocalLanguages.Add(currentlyDownloadingLanguage); //UpdateLanguagesWithCurrentManifest(); } } catch (Exception ex) { Console.WriteLine(ex.Message); if (ex.GetType() != typeof(TaskCanceledException) && ex.GetType() != typeof(OperationCanceledException) && currentlyDownloadingLanguage != null) { downloadErrors.Add(ex); } } finally { Exception error = null; currentlyDownloadingLanguage.IsDownloading = false; var errors = downloadErrors.Where(e => e != null); if (errors != null && errors.Count() > 0) { error = errors.ElementAt(0); } if (error != null) { DownloadableLanguagesError = error; currentlyDownloadingLanguage.DownloadPercentage = 0; } else { currentlyDownloadingLanguage.DownloadPercentage = 100; } if (!cancelled) { completion?.Invoke(currentlyDownloadingLanguage, error); } } }