internal async Task <Dictionary <string, bool> > GenerateMoveSourceFiles( AppSettingsPublishProfiles profile, IReadOnlyCollection <FileIndexItem> fileIndexItemsList, string outputParentFullFilePathFolder, bool moveSourceFiles) { _toCreateSubfolder.Create(profile, outputParentFullFilePathFolder); foreach (var item in fileIndexItemsList) { // input: item.FilePath var outputPath = _overlayImage.FilePathOverlayImage(outputParentFullFilePathFolder, item.FilePath, profile); await _hostFileSystemStorage.WriteStreamAsync(_subPathStorage.ReadStream(item.FilePath), outputPath); // only delete when using in cli mode if (moveSourceFiles) { _subPathStorage.FileDelete(item.FilePath); } } return(fileIndexItemsList.ToDictionary(item => _overlayImage.FilePathOverlayImage(item.FilePath, profile), item => profile.Copy)); }
/// <summary> /// Generate loop of Jpeg images with overlay image /// With Retry included /// </summary> /// <param name="profile">contains sizes</param> /// <param name="fileIndexItemsList">list of items to generate jpeg for</param> /// <param name="outputParentFullFilePathFolder">outputParentFullFilePathFolder</param> /// <param name="delay">when failed output, has default value</param> /// <returns></returns> internal async Task <Dictionary <string, bool> > GenerateJpeg(AppSettingsPublishProfiles profile, IReadOnlyCollection <FileIndexItem> fileIndexItemsList, string outputParentFullFilePathFolder, int delay = 6) { _toCreateSubfolder.Create(profile, outputParentFullFilePathFolder); foreach (var item in fileIndexItemsList) { var outputPath = _overlayImage.FilePathOverlayImage(outputParentFullFilePathFolder, item.FilePath, profile); async Task <bool> ResizerLocal() { return(await Resizer(outputPath, profile, item)); } try { await RetryHelper.DoAsync(ResizerLocal, TimeSpan.FromSeconds(delay)); } catch (AggregateException e) { _logger.LogError($"[ResizerLocal] Skip due errors: (catch-ed exception) {item.FilePath} {item.FileHash}"); foreach (var exception in e.InnerExceptions) { _logger.LogError("[ResizerLocal] " + exception.Message, exception); } } } return(fileIndexItemsList.ToDictionary(item => _overlayImage.FilePathOverlayImage(item.FilePath, profile), item => profile.Copy)); }
private async Task <bool> ResizeOverlayImageShared(Image sourceImage, Image overlayImage, Stream outputStream, AppSettingsPublishProfiles profile, string outputSubPath) { sourceImage.Mutate(x => x.AutoOrient()); sourceImage.Mutate(x => x .Resize(profile.SourceMaxWidth, 0, KnownResamplers.Lanczos3) ); overlayImage.Mutate(x => x .Resize(profile.OverlayMaxWidth, 0, KnownResamplers.Lanczos3) ); int xPoint = sourceImage.Width - overlayImage.Width; int yPoint = sourceImage.Height - overlayImage.Height; sourceImage.Mutate(x => x.DrawImage(overlayImage, new Point(xPoint, yPoint), 1F)); await sourceImage.SaveAsJpegAsync(outputStream); outputStream.Seek(0, SeekOrigin.Begin); await _hostFileSystem.WriteStreamAsync(outputStream, outputSubPath); return(true); }
public void AppSettingsPublishProfilesTest_OverlayMaxWidthTestMoreThan100() { var model = new AppSettingsPublishProfiles(); model.OverlayMaxWidth = 101; Assert.AreEqual(101, model.OverlayMaxWidth); }
/// <summary> /// Read from _iStorage to _hostFileSystem /// </summary> /// <param name="itemFilePath">input Image</param> /// <param name="outputFullFilePath">location where to store</param> /// <param name="profile">image profile that contains sizes</param> /// <exception cref="FileNotFoundException">source image not found</exception> public Task <bool> ResizeOverlayImageLarge(string itemFilePath, string outputFullFilePath, AppSettingsPublishProfiles profile) { if (string.IsNullOrWhiteSpace(itemFilePath)) { throw new ArgumentNullException(nameof(itemFilePath)); } if (!_iStorage.ExistFile(itemFilePath)) { throw new FileNotFoundException("subPath " + itemFilePath); } if (_hostFileSystem.ExistFile(outputFullFilePath)) { return(Task.FromResult(false)); } if (!_hostFileSystem.ExistFile(profile.Path)) { throw new FileNotFoundException($"overlayImage is missing in profile.Path: {profile.Path}"); } return(ResizeOverlayImageLargeInternal(itemFilePath, outputFullFilePath, profile)); }
public string FilePathOverlayImage(string outputParentFullFilePathFolder, string sourceFilePath, AppSettingsPublishProfiles profile) { var result = PathHelper.AddBackslash(outputParentFullFilePathFolder) + FilePathOverlayImage(sourceFilePath, profile); return(result); }
public void GetExtensionWithDot_Fallback() { var model = new AppSettingsPublishProfiles(); var result = model.GetExtensionWithDot("test.png"); Assert.AreEqual(".png", result); }
public string FilePathOverlayImage(string sourceFilePath, AppSettingsPublishProfiles profile) { var result = profile.Folder + _appSettings.GenerateSlug( Path.GetFileNameWithoutExtension(sourceFilePath), true) + profile.Append + profile.GetExtensionWithDot(sourceFilePath); return(result); }
public void AppSettingsPublishProfilesTest_Path_null() { var model = new AppSettingsPublishProfiles { Path = null }; Assert.IsTrue(model.Path.Contains("default.png")); }
public void AppSettingsPublishProfilesTest_AddSlash() { var model = new AppSettingsPublishProfiles(); model.Folder = "/test"; var getFolder = model.Folder; Assert.AreEqual("/test/", getFolder); }
public void AppSettingsPublishProfilesTest_Path_AssemblyDirectory() { var model = new AppSettingsPublishProfiles { Path = "{AssemblyDirectory}" + Path.DirectorySeparatorChar + "test.jpg" }; // in real world this is not always BaseDirectoryProject Assert.AreEqual(AppDomain.CurrentDomain.BaseDirectory + "test.jpg", model.Path); }
public void AppSettingsPublishProfilesTest_FolderNull() { var model = new AppSettingsPublishProfiles(); model.Folder = null; var getFolder = model.Folder; Assert.AreEqual(string.Empty, getFolder); }
public void GetExtensionWithDot_Nothing() { var model = new AppSettingsPublishProfiles { }; var result = model.GetExtensionWithDot(""); Assert.AreEqual("", result); }
public void GetExtensionWithDot_Jpeg() { var model = new AppSettingsPublishProfiles { ContentType = TemplateContentType.Jpeg }; var result = model.GetExtensionWithDot("test.png"); Assert.AreEqual(".jpg", result); }
/// <summary> /// [Internal] Without checks if input is valid - Read from thumbnail storage /// </summary> /// <param name="itemFilePath">input Image</param> /// <param name="outputFullFilePath">location where to store</param> /// <param name="profile">image profile that contains sizes</param> private async Task <bool> ResizeOverlayImageThumbnailsInternal( string itemFilePath, string outputFullFilePath, AppSettingsPublishProfiles profile) { using (var sourceImageStream = _thumbnailStorage.ReadStream(itemFilePath)) using (var sourceImage = await Image.LoadAsync(sourceImageStream)) using (var overlayImageStream = _hostFileSystem.ReadStream(profile.Path)) // for example a logo using (var overlayImage = await Image.LoadAsync(overlayImageStream)) using (var outputStream = new MemoryStream()) { return(await ResizeOverlayImageShared(sourceImage, overlayImage, outputStream, profile, outputFullFilePath)); } }
public async Task <bool> ResizeOverlayImageLarge(string itemFilePath, string outputFullFilePath, AppSettingsPublishProfiles profile) { if (itemFilePath == "/corrupt.jpg" || itemFilePath == "corrupt") { await _storage.WriteStreamAsync(new MemoryStream(new CreateAnImageCorrupt().Bytes), outputFullFilePath); return(true); } return(await _storage.WriteStreamAsync(new MemoryStream(FakeCreateAn.CreateAnImageNoExif.Bytes), outputFullFilePath)); }
public void AppSettingsPublishProfilesString() { var data = new AppSettingsPublishProfiles().ToString(); Assert.IsTrue(data.Contains("ContentType")); Assert.IsTrue(data.Contains("SourceMaxWidth")); Assert.IsTrue(data.Contains("OverlayMaxWidth")); Assert.IsTrue(data.Contains("Path")); Assert.IsTrue(data.Contains("Folder")); Assert.IsTrue(data.Contains("Append")); Assert.IsTrue(data.Contains("OverlayMaxWidth")); Assert.IsTrue(data.Contains("Template")); Assert.IsTrue(data.Contains("Prepend")); Assert.IsTrue(data.Contains("MetaData")); Assert.IsTrue(data.Contains("Copy")); }
public async Task MoveSourceFiles_False() { var profile = new AppSettingsPublishProfiles { ContentType = TemplateContentType.MoveSourceFiles, Folder = "src", }; var storage = new FakeIStorage(new List <string> { "/" }, new List <string> { "/test.jpg" }); var selectorStorage = new FakeSelectorStorage(storage); var appSettings = new AppSettings { PublishProfiles = new Dictionary <string, List <AppSettingsPublishProfiles> > { { "default", new List <AppSettingsPublishProfiles> { profile } } }, Verbose = true }; var service = new WebHtmlPublishService(new PublishPreflight(appSettings, new ConsoleWrapper()), selectorStorage, appSettings, new FakeExifTool(storage, appSettings), new FakeIOverlayImage(selectorStorage), new ConsoleWrapper(), new FakeIWebLogger()); await service.GenerateMoveSourceFiles(profile, new List <FileIndexItem> { new FileIndexItem("/test.jpg") }, "/", false); // False situation Assert.IsTrue(storage.GetAllFilesInDirectoryRecursive("/") .FirstOrDefault(p => p != null && p.Contains("src/test.jpg")) != null); // is True instead of False Assert.IsTrue(storage.ExistFile("/test.jpg")); }
internal async Task <Dictionary <string, bool> > GenerateWebHtml(List <AppSettingsPublishProfiles> profiles, AppSettingsPublishProfiles currentProfile, string itemName, string[] base64ImageArray, IEnumerable <FileIndexItem> fileIndexItemsList, string outputParentFullFilePathFolder) { if (string.IsNullOrEmpty(currentProfile.Template)) { _console.WriteLine("CurrentProfile Template not configured"); return(new Dictionary <string, bool>()); } // Generates html by razorLight var viewModel = new WebHtmlViewModel { ItemName = itemName, Profiles = profiles, AppSettings = _appSettings, CurrentProfile = currentProfile, Base64ImageArray = base64ImageArray, // apply slug to items, but use it only in the copy FileIndexItems = fileIndexItemsList.Select(c => c.Clone()).ToList(), }; // add to IClonable foreach (var item in viewModel.FileIndexItems) { item.FileName = _appSettings.GenerateSlug(item.FileCollectionName, true) + Path.GetExtension(item.FileName); } // has a direct dependency on the filesystem var embeddedResult = await new ParseRazor(_hostFileSystemStorage) .EmbeddedViews(currentProfile.Template, viewModel); var stream = new PlainTextFileHelper().StringToStream(embeddedResult); await _hostFileSystemStorage.WriteStreamAsync(stream, Path.Combine(outputParentFullFilePathFolder, currentProfile.Path)); _console.Write(_appSettings.IsVerbose() ? embeddedResult + "\n" : "•"); return(new Dictionary <string, bool> { { currentProfile.Path.Replace(outputParentFullFilePathFolder, string.Empty), currentProfile.Copy } }); }
/// <summary> /// Create SubFolders by the profile.Folder setting /// </summary> /// <param name="profile">config</param> /// <param name="parentFolder">root folder</param> public void Create(AppSettingsPublishProfiles profile, string parentFolder) { // check if subfolder '1000' exist on disk // used for moving subfolders first var profileFolderStringBuilder = new StringBuilder(); if (!string.IsNullOrEmpty(parentFolder)) { profileFolderStringBuilder.Append(parentFolder); profileFolderStringBuilder.Append('/'); } profileFolderStringBuilder.Append(profile.Folder); if (_hostFileSystemStorage.IsFolderOrFile(profileFolderStringBuilder.ToString()) == FolderOrFileModel.FolderOrFileTypeList.Deleted) { _hostFileSystemStorage.CreateDirectory(profileFolderStringBuilder.ToString()); } }
public Dictionary <string, bool> CopyContent( AppSettingsPublishProfiles profile, string outputParentFullFilePathFolder) { _toCreateSubfolder.Create(profile, outputParentFullFilePathFolder); var parentFolder = PathHelper.AddBackslash( _appSettings.GenerateSlug(profile.Folder, true)); var copyResult = new Dictionary <string, bool>(); var files = _hostStorage.GetAllFilesInDirectory(GetContentFolder()).ToList(); foreach (var file in files) { var subPath = parentFolder + Path.GetFileName(file); copyResult.Add(subPath, true); var fillFileOutputPath = Path.Combine(outputParentFullFilePathFolder, subPath); if (!_hostStorage.ExistFile(fillFileOutputPath)) { _hostStorage.FileCopy(file, fillFileOutputPath); } } return(copyResult); }
/// <summary> /// Resize image with overlay /// </summary> /// <param name="outputPath">absolute path of output on host disk</param> /// <param name="profile">size of output, overlay size, must contain metaData </param> /// <param name="item">database item with filePath</param> /// <returns>true when success</returns> /// <exception cref="DecodingException">when output is not valid</exception> private async Task <bool> Resizer(string outputPath, AppSettingsPublishProfiles profile, FileIndexItem item) { // for less than 1000px if (profile.SourceMaxWidth <= 1000 && _thumbnailStorage.ExistFile(ThumbnailNameHelper. Combine(item.FileHash, ThumbnailSize.Large))) { await _overlayImage.ResizeOverlayImageThumbnails(item.FileHash, outputPath, profile); } else if (profile.SourceMaxWidth <= 2000 && _thumbnailStorage.ExistFile(ThumbnailNameHelper. Combine(item.FileHash, ThumbnailSize.ExtraLarge))) { await _overlayImage.ResizeOverlayImageThumbnails( ThumbnailNameHelper.Combine(item.FileHash, ThumbnailSize.ExtraLarge), outputPath, profile); } else if (_subPathStorage.ExistFile(item.FilePath)) { // Thumbs are 2000 px (and larger) await _overlayImage.ResizeOverlayImageLarge(item.FilePath, outputPath, profile); } if (profile.MetaData) { await MetaData(item, outputPath); } var imageFormat = ExtensionRolesHelper.GetImageFormat(_hostFileSystemStorage.ReadStream(outputPath, 160)); if (imageFormat == ExtensionRolesHelper.ImageFormat.jpg) { return(true); } _hostFileSystemStorage.FileDelete(outputPath); throw new DecodingException("[WebHtmlPublishService] image output is not valid"); }
public string FilePathOverlayImage(string sourceFilePath, AppSettingsPublishProfiles profile) { return(new OverlayImage(null, new AppSettings()).FilePathOverlayImage( sourceFilePath, profile)); }
public async Task <bool> ResizeOverlayImageThumbnails(string itemFileHash, string outputFullFilePath, AppSettingsPublishProfiles profile) { return(await ResizeOverlayImageLarge(itemFileHash, outputFullFilePath, profile)); }
public string FilePathOverlayImage(string outputParentFullFilePathFolder, string sourceFilePath, AppSettingsPublishProfiles profile) { return(new OverlayImage(null, new AppSettings()).FilePathOverlayImage(outputParentFullFilePathFolder, sourceFilePath, profile)); }