/// <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."); }); }
public void DetermineUniqueFilename_given_duplicate_filename_returns_unique_filename() { var dir = $"test_{GetType().Name}_DetermineUniqueFilename"; var directory = Path.Combine(Directory.GetCurrentDirectory(), dir); var inputname = "notunique.jpg"; var expectedname = "notunique (2).jpg"; if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } if (File.Exists(Path.Combine(directory, expectedname))) { File.Delete(Path.Combine(directory, expectedname)); } File.Create(Path.Combine(directory, "notunique.jpg")).Dispose(); File.Create(Path.Combine(directory, "notunique (1).jpg")).Dispose(); var output = Filenamer.DetermineUniqueFilename(Path.Combine(directory, inputname)); Assert.Equal(Path.Combine(directory, expectedname), output); }
public void DetermineUniqueFilename_given_unique_filename_returns_identical_filename() { var dir = $"test_{GetType().Name}_DetermineUniqueFilename"; var directory = Path.Combine(Directory.GetCurrentDirectory(), dir); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } var path = Path.Combine(directory, "unique.test"); var output = Filenamer.DetermineUniqueFilename(path); Assert.Equal(path, output); }
/// <summary> /// <see cref="IHandler{T,K}.FetchContent(x,string,x,ICollection{string})"/> /// </summary> public override async Task FetchContent(LocalDirectory parsedSource, string targetFolder, LocalFilter filter, ICollection <string> outputLog, bool saveNestedCollectionsInNestedFolders = false) { await Task.Run(() => { if (parsedSource.GetImages() != null) { outputLog.Add($"Starting filtering 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 => { var localTargetFolder = targetFolder; if (saveNestedCollectionsInNestedFolders) { var path = Path.GetDirectoryName(image.ImagePath); if (!string.IsNullOrWhiteSpace(path)) { Debug.Assert(parsedSource.Directory.Length <= path.Length, $"Directory length longer than path.\nDirectory: {parsedSource.Directory}\nPath: {path}"); Debug.Assert(path.Substring(0, parsedSource.Directory.Length) == parsedSource.Directory, $"Directory doesn't exist in image path.\nDirectory: {parsedSource.Directory}\nPath: {path}"); var sourceDir = new DirectoryInfo(parsedSource.Directory); var innerFolders = new List <string>(); var innerFolder = new DirectoryInfo(path); while (sourceDir.FullName != innerFolder?.FullName) { innerFolders.Add(innerFolder.Name); innerFolder = innerFolder.Parent; } innerFolders.Add(targetFolder); innerFolders.Reverse(); localTargetFolder = Path.Combine(innerFolders.ToArray()); } } using (image) { var imageName = Filenamer.Clean(image.GetImageName().Result); try { if (filter(image.GetHeight().Result, image.GetWidth().Result, image.GetAspectRatio().Result)) { //Dont create the folder unless we actually have something to save in it. if (!Directory.Exists(localTargetFolder)) { Directory.CreateDirectory(localTargetFolder); } var path = Filenamer.DetermineUniqueFilename(Path.Combine(localTargetFolder, imageName)); File.WriteAllBytes(path, image.GetImage().Result); WriteToLog(sync, outputLog, $"Image copied: {imageName}"); } else { WriteToLog(sync, outputLog, $"Image skipped: {imageName}"); } } catch (IOException) { WriteToLog(sync, outputLog, $"IO Failure - Error occured while saving or loading image: {imageName}"); } } }); } outputLog.Add("Filtering 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."); }); }
/// <summary> /// <see cref="IHandler{T,K}.FetchContent(x,string,x,ICollection{string})"/> /// </summary> public override async Task FetchContent(RedditListing parsedSource, string targetFolder, RedditFilter filter, ICollection <string> outputLog, bool saveNestedCollectionsInNestedFolders = false) { await Task.Run(() => { if (parsedSource.GetCollections() != null) { outputLog.Add($"Starting download of {parsedSource.GetImages().Count()} images."); foreach (var redditPost in parsedSource.GetCollections().Where(image => image != null)) { if (redditPost.GetImages() == null) { continue; } var sync = new object(); var localTargetFolder = targetFolder; //If the images will be saved in their own album, then there is no reason to prefix them with the reddit-title, since the folder has that info already. string imageNamePrefix; if (redditPost.IsAlbum && saveNestedCollectionsInNestedFolders) { localTargetFolder = Path.Combine(localTargetFolder, Filenamer.Clean(redditPost.ShortTitle)); imageNamePrefix = string.Empty; } else { imageNamePrefix = Filenamer.Clean(redditPost.ShortTitle) + " - "; } //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(redditPost.GetImages().Where(image => image != null), parallelOptions, image => { using (image) { var imageName = imageNamePrefix + Filenamer.Clean(image.GetImageName().Result); try { if (filter(image.GetHeight().Result, image.GetWidth().Result, redditPost.Over_18, redditPost.Album != null, image.GetAspectRatio().Result)) { //Dont create the folder unless we actually have something to save in it. if (!Directory.Exists(localTargetFolder)) { Directory.CreateDirectory(localTargetFolder); } var path = Filenamer.DetermineUniqueFilename(Path.Combine(localTargetFolder, 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."); }); }