/// <summary> /// <see cref="IHandler{T,K}.FetchContent(x,string,x,ICollection{string})"/> /// </summary> public override async Task FetchContent(IApiCollection <IApiImage> parsedSource, string targetFolder, ImgurFilter filter, ICollection <string> outputLog) { await Task.Run(async() => { if (parsedSource.GetImages() != null) { outputLog.Add($"Starting download of {parsedSource.GetImages().Count()} images."); var sync = new object(); foreach (var image in parsedSource.GetImages().Where(image => image != null).AsParallel()) { var imageName = Filenamer.Clean(await image.GetImageName()); try { if (filter(await image.GetHeight(), await image.GetWidth(), await image.GetAspectRatio())) { var path = Filenamer.DetermineUniqueFilename(Path.Combine(targetFolder, imageName)); var fileContents = await image.GetImage(); File.WriteAllBytes(path, fileContents); lock (sync) { outputLog.Add($"Image saved: {imageName}"); image.Dispose(); } } else { lock (sync) { outputLog.Add($"Image skipped: {imageName}"); image.Dispose(); } } } catch (WebException) { lock (sync) { outputLog.Add($"Unable to download image: {imageName}"); image.Dispose(); } } catch (IOException) { lock (sync) { outputLog.Add($"IO Failure - Error occured while saving image: {imageName}"); image.Dispose(); } } } } outputLog.Add("Download finished."); }); }
/// <summary> /// <see cref="IHandler{T,K}.FetchContent(x,string,x,ICollection{string})"/> /// </summary> /// <param name="saveNestedCollectionsInNestedFolders">Imgur collections /// cannot contain nested albums, so the parameter has no effect.</param> public override async Task FetchContent(IApiCollection <IApiImage> parsedSource, string targetFolder, ImgurFilter filter, ICollection <string> outputLog, bool saveNestedCollectionsInNestedFolders = false) { await Task.Run(() => { if (parsedSource.GetImages() != null) { outputLog.Add($"Starting download of {parsedSource.GetImages().Count()} images."); var sync = new object(); //Limit degree of parallelism to avoid sending too many http-requests at the same time. // 8 seems like a reasonable amount of requests to have in-flight at a time. var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = 8 }; Parallel.ForEach(parsedSource.GetImages().Where(image => image != null), parallelOptions, image => { using (image) { var imageName = Filenamer.Clean(image.GetImageName().Result); try { if (filter(image.GetHeight().Result, image.GetWidth().Result, image.GetAspectRatio().Result)) { var path = Filenamer.DetermineUniqueFilename(Path.Combine(targetFolder, imageName)); var fileContents = image.GetImage().Result; File.WriteAllBytes(path, fileContents); WriteToLog(sync, outputLog, $"Image saved: {imageName}"); } else { WriteToLog(sync, outputLog, $"Image skipped: {imageName}"); } } catch (WebException) { WriteToLog(sync, outputLog, $"Unable to download image: {imageName}"); } catch (IOException) { WriteToLog(sync, outputLog, $"IO Failure - Error occured while saving image: {imageName}"); } catch (AggregateException ex) { if (ex.InnerException is WebException) { WriteToLog(sync, outputLog, $"Unable to download image: {imageName}"); } else { WriteToLog(sync, outputLog, $"Unknown error occured for {imageName}. Error message is: " + ex.InnerException.Message); } } } }); } outputLog.Add("Download finished."); }); }