
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Constants\ConfigurationNodeNames.cs

namespace xStorageService.Constants {
    public partial struct ConfigurationNodeNames {
        public const string STORAGE_SERVICE_NODE_NAME = "StorageConfiguration";
    }

}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Constants\FileExtensions.cs

using xExceptions.Attributes;

namespace xStorageService.Constants {
    public enum FileExtensions {
        //
        // Document
        [StringValue (".txt")]
        TEXT = 100,

        [StringValue (".pdf")]
        PDF = 101,

        [StringValue (".ppt")]
        PPT = 102,

        [StringValue (".pptx")]
        PPTX = 103,

        [StringValue (".odp")]
        ODP = 104,

        [StringValue (".pps")]
        PPS = 105,

        [StringValue (".ods")]
        ODS = 106,

        [StringValue (".xlr")]
        XLR = 107,

        [StringValue (".xls")]
        XLS = 108,

        [StringValue (".xlsx")]
        XLSX = 109,

        [StringValue (".xml")]
        XML = 110,

        [StringValue (".doc")]
        DOC = 111,

        [StringValue (".docx")]
        DOCX = 112,

        [StringValue (".odt")]
        ODT = 113,

        [StringValue (".rtf")]
        RTF = 114,

        [StringValue (".tex")]
        TEX = 115,

        [StringValue (".wpd")]
        WPD = 116,

        [StringValue (".md")]
        MD = 117,

        //
        // Archive
        [StringValue (".zip")]
        ZIP = 200,

        //
        // Internal Supports 
        [StringValue (".ttf")]
        TTF = 300,

        [StringValue (".js")]
        JAVASCRIPT = 301,

        [StringValue (".css")]
        CSS = 302,

        [StringValue (".htm")]
        HTM = 303,

        [StringValue (".html")]
        HTML = 304,

        [StringValue (".sdw")]
        SAHER_DASHBOARD_WIDGET = 305,

        [StringValue (".sdwmanifest")]
        SAHER_DASHBOARD_WIDGET_MANIFEST = 306,

        //
        // Video
        [StringValue (".mp4")]
        MP4 = 400,

        [StringValue (".avi")]
        AVI = 401,

        [StringValue (".mpg")]
        MPG = 402,

        [StringValue (".mpeg")]
        MPEG = 403,

        [StringValue (".wmv")]
        WMV = 404,

        //
        // Audio
        [StringValue (".mp3")]
        MP3 = 500,

        [StringValue (".ogg")]
        OGG = 501,

        [StringValue (".wav")]
        WAV = 502,

        [StringValue (".wma")]
        WMA = 503,

        //
        // Image
        [StringValue (".png")]
        PNG = 600,

        [StringValue (".jpeg")]
        JPEG = 601,

        [StringValue (".jpg")]
        JPG = 602,

        // [StringValue (".ico")]
        // ICON = 603,

        [StringValue (".gif")]
        GIF = 604,

        [StringValue (".bmp")]
        BITMAP = 605,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\DI\XDIHelperExtension.cs

using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using xCommons.Extensions;
using xExceptions.Constants;
using xStorageService.Constants;
using xStorageService.Helpers;
using xStorageService.Interfaces;
using xStorageService.Models;
using xStorageService.Providers;

namespace xStorageService.DI {
    public static partial class XDIHelperExtension {
        /// <summary>
        /// Retrieve XStorage Configuration from AppSettings 
        /// </summary>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static XStorageConfiguration GetXStorageConfiguration (this IConfiguration configuration) {
            //
            var storageConfigurationSection = configuration.GetSection (ConfigurationNodeNames.STORAGE_SERVICE_NODE_NAME);
            return storageConfigurationSection.Get<XStorageConfiguration> ();
        }

        /// <summary>
        /// Register XStorage Configuration 
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXStorageConfiguration (
            this IServiceCollection services,
            IConfiguration configuration
        ) {
            //
            // Check wwwroot Folder ...
            if (!Directory.Exists ("wwwroot")) {
                Directory.CreateDirectory ("wwwroot");
            }

            //
            // Retrieve and Register XStorage Configurations ...
            var xStorageConfiguration = configuration.GetXStorageConfiguration ();
            if (xStorageConfiguration.IsNull ()) {
                XException.InvalidConfiguration.Throw ();
            }

            //
            xStorageConfiguration.BaseFolder = Path.Combine (Directory.GetCurrentDirectory (), "wwwroot");
            xStorageConfiguration.RootFolder = Directory.GetDirectoryRoot (xStorageConfiguration.BaseFolder);

            //
            services.AddSingleton<XStorageConfiguration> (xStorageConfiguration);
        }

        /// <summary>
        /// Register XStorage Service 
        /// </summary>
        /// <param name="services"></param>
        /// <param name="config"></param>
        public static void AddXStorageService (
            this IServiceCollection services,
            IConfiguration configuration
        ) {
            //
            // Register and Retrieve XStorage Configuration
            services.AddXStorageConfiguration (configuration);
            var xStorageConfiguration = services.GetRegisteredService<XStorageConfiguration> ();

            //
            // Add File Provider ...
            services.AddSingleton<IFileProvider> (
                new PhysicalFileProvider (xStorageConfiguration.BaseFolder)
            );

            //
            // Register XStorageHelper Service ...
            services.AddSingleton<XStorageHelper> ();

            //
            // Register ThumbnailHelper ... 
            services.AddSingleton<IXThumbnailProvider, XThumbnailProvider> ();

            //
            // Register Storage Provider ...
            services.AddScoped<IXStorageProvider, XStorageProvider> ();

            //
            // StorageService Preperation...
            var xStorageService = services.GetRegisteredService<IXStorageProvider> ();
            xStorageService.Prepare ();
        }

        /// <summary>
        /// Use XStorage Service 
        /// </summary>
        /// <param name="app"></param>
        public static void UseXStorageService (this IApplicationBuilder app) {
            //
            // Get Instance of Scope and Service and Prepare Folder Structure ...
            using (var scope = app.ApplicationServices.CreateScope ()) {
                //
                var storageProvider = scope.ServiceProvider.GetService<IXStorageProvider> ();

                //
                storageProvider.Prepare ();
            }

            //
            // available Static Files ...
            app.UseStaticFiles ();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Helpers\XStorageHelper.cs

using System;
using System.IO;
using System.Linq;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xStorageService.Constants;

namespace xStorageService.Helpers {
    public partial class XStorageHelper {

        private int[] DocumentTypeThreshold = new int[] { 99, 307 };
        private int[] ImageTypeThreshold = new int[] { 599, 606 };
        private int[] AudioTypeThreshold = new int[] { 499, 504 };
        private int[] VideoTypeThreshold = new int[] { 399, 405 };

        public XStorageHelper () { }

        /// <summary>
        /// Retrieve FileType
        /// </summary>
        /// <param name="fileExtension"></param>
        /// <returns></returns>
        public XFileType GetType (int fileExtension) {
            //
            // Compare File Extension Integer Value and 
            // Find Propper Type for it ...
            if (fileExtension > DocumentTypeThreshold[0] && fileExtension < DocumentTypeThreshold[1]) {
                return XFileType.Document;
            } else if (fileExtension > VideoTypeThreshold[0] && fileExtension < VideoTypeThreshold[1]) {
                return XFileType.Video;
            } else if (fileExtension > AudioTypeThreshold[0] && fileExtension < AudioTypeThreshold[1]) {
                return XFileType.Audio;
            } else if (fileExtension > ImageTypeThreshold[0] && fileExtension < ImageTypeThreshold[1]) {
                return XFileType.Image;
            } else {
                //
                // if not in case return Document Type
                return XFileType.Document;
            }
        }

        /// <summary>
        /// Retrieve a File Type 
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public XFileType GetType (string fileName) {
            //
            if (fileName.IsNullOrEmpty ()) {
                XException.InavlidFile.Throw ();
            }

            //
            var ext = GetFileExtension (fileName);
            var extType = GetExtensionType (ext);
            return GetType (extType);
        }

        /// <summary>
        ///     used for validating Extension in Widget Upload ...
        /// </summary>
        /// <returns>an string array</returns>
        public string[] GetAllowedExtensionsForWidgetUpload () {
            return new [] {
                FileExtensions.SAHER_DASHBOARD_WIDGET.GetStringValue ()
            };
        }

        /// <summary>
        /// Get a Files Extension string
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetFileExtension (string fileName) {
            //
            // Validate Args ...
            if (fileName.IsNullOrEmpty ()) {
                return null;
            }

            //
            var fileExt = "";
            try {
                fileExt = Path.GetExtension (fileName);
            } catch { }

            //
            return fileExt;
        }

        /// <summary>
        /// Get a File Name Without it's Extension
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetFileNameWithoutExtension (string fileName) {
            //
            // Validate Args ...
            if (fileName.IsNullOrEmpty ()) {
                return null;
            }

            //
            var fileNameWithoutExt = "";
            try {
                fileNameWithoutExt = Path
                    .GetFileNameWithoutExtension (fileName);
            } catch { }

            //
            return fileNameWithoutExt;
        }

        /// <summary>
        /// Get File Extension Type
        /// </summary>
        /// <param name="fileExtension"></param>
        /// <returns></returns>
        public int GetExtensionType (string fileExtension) {
            //
            foreach (var extItem in Enum
                    .GetValues (typeof (FileExtensions))
                    .Cast<FileExtensions> ()) {
                if (extItem.GetStringValue ()
                    .Contains (fileExtension.ToLower ())) {
                    return (int) extItem;
                }
            }

            //
            return -1;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Interfaces\IXStorageProvider.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
using xCommons.Constants;
using xModels.Dtos;
using xStorageService.Constants;
using xStorageService.Helpers;
using xStorageService.Models;

namespace xStorageService.Interfaces
{
    public partial interface IXStorageProvider
    {
        XStorageConfiguration Configuration { get; }
        XStorageHelper StorageHelper { get; }
        IFileProvider FileProvider { get; }
        IXThumbnailProvider ThumbnailProvider { get; }

        //
        #region Special Folders Path Getter (s) ...
        string GetStorageFolderPath();
        string GetTempFolderPath();
        string GetThumbFolderPath();
        string GetUploadsFolderPath();
        string GetWidgetsFolderPath();
        string GetImageFolderPath();
        string GetAudioFolderPath();
        string GetVideoFolderPath();
        string GetDocumentFolderPath();
        string FilePathResolver(string fullPath);
        string ConvertToFileUrl(string fullPath);
        #endregion

        //
        #region Prepare Storage Structure ...
        void Prepare();
        #endregion

        //
        #region Validators ...
        bool IsFolderExists(string path);
        bool IsFileExists(string filePath);
        bool IsSupportThumb(string fileName);
        bool IsSupportThumb(XFileType type);
        void ValidateFileExists(string filePath);
        void ValidateFileModel(XFileDto file);
        void ValidateFile(IFormFile file);
        void ValidateProfileImage(IFormFile file);
        #endregion

        //
        #region Generators ...
        string NewFileName();
        string GenerateThumbName(string fileName);
        string GetNewFileName(string fileName);
        #endregion

        //
        #region Tools Actions ...

        string GetFileExtension(string fileName);
        string GetFileNameWithoutExtension(string fileName);
        FileExtensions GetFileExtensionType(string fileName);
        XFileType GetFileType(string fileName);
        XFileType GetFileType(FileExtensions fileExtension);
        string GetThumbnailFileFullPath(string thumFileName);
        string GetRelatedThumbnailFullPath(string fileName);
        string GetFileTypeFolderPath(XFileType type);
        string GetFileFolderPath(
            string fileName,
            bool isTemp = false,
            bool isWidget = false
        );
        string GetFileFullPath(
            string fileName,
            bool isTemp = false,
            bool isWidget = false
        );
        Task<string> SaveFileAsync(
            IFormFile file,
            bool isTemp = false,
            bool isWidget = false,
            CancellationToken cancellationToken = default
        );
        void DeleteFile(
            string fileFullPath,
            bool forceFileExists = true,
            Exception exception = null
        );
        ICollection<string> DeleteFiles(
            ICollection<string> fileFullPaths,
            bool forceFileExists = true,
            Exception exception = null
        );
        // Task CreateThumbnail (XFile file);
        Task CreateThumbnail(
            XFileDto file,
            CancellationToken cancellationToken = default
        );
        Task CreateThumbnail(
            string fileName,
            CancellationToken cancellationToken = default
        );
        Task<XFileResult> HandleProfileImageSave(
            IFormFile file,
            CancellationToken cancellationToken = default
        );
        Task<XFileResult> HandleFileSave(
            IFormFile file,
            CancellationToken cancellationToken = default
        );
        Task<IEnumerable<XFileResult>> HandleFilesSave(
            IFormFileCollection files,
            CancellationToken cancellationToken = default
        );
        #endregion    
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Interfaces\IXThumbnailProvider.cs

using xStorageService.Models;

namespace xStorageService.Interfaces {
    public partial interface IXThumbnailProvider {
        void SetTempFolder (string folder);
        XImageInfo GetImageInfo (string filePath);
        void ResizeImage (
            string filePath,
            string resizedFilePath,
            int size,
            int quality
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Models\XFileResult.cs

namespace xStorageService.Models {
    public partial class XFileResult {
        public string Name { get; set; }
        public string FileName { get; set; }
        public string FilePath { get; set; }
        public string Thmbnail { get; set; }
        public string ThmbnailPath { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Models\XImageInfo.cs

using ImageMagick;

namespace xStorageService.Models {
    public partial class XImageInfo {
        public Interlace Interlace { get; }
        public int Height { get; }
        public MagickFormat Format { get; }
        public string FileName { get; }
        public Density Density { get; }
        public CompressionMethod Compression { get; }
        public ColorSpace ColorSpace { get; }
        public int Width { get; }
        public int Quality { get; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Models\XStorageConfiguration.cs

namespace xStorageService.Models {
    public partial class XStorageConfiguration {
        /// <summary>
        /// Base Path of Identity Host Server
        /// </summary>
        /// <value></value>
        public string IdentityAuthority { get; set; }

        /// <summary>
        /// Base Path of Host Server
        /// </summary>
        /// <value></value>
        public string Authority { get; set; }

        /// <summary>
        /// Root Directory Of File Storage
        /// </summary>
        /// <value></value>        
        public string RootFolder { get; set; }

        /// <summary>
        /// Base Root of Usable Folder for Files
        /// </summary>
        /// <value></value>
        public string BaseFolder { get; set; }

        /// <summary>
        /// Storage Folder Label
        /// </summary>
        /// <value></value>
        public string Storage { get; set; }

        /// <summary>
        /// Temp Folder Label
        /// </summary>
        /// <value></value>
        public string Temp { get; set; }

        /// <summary>
        /// Thumb Folder Label
        /// </summary>
        /// <value></value>
        public string Thumb { get; set; }

        /// <summary>
        /// Uploads Folder Label
        /// </summary>
        /// <value></value>
        public string Uploads { get; set; }

        /// <summary>
        /// Widgets Folder Label
        /// </summary>
        /// <value></value>
        public string Widgets { get; set; }

        /// <summary>
        /// Images Folder Label
        /// </summary>
        /// <value></value>
        public string Image { get; set; }

        /// <summary>
        /// Audios Folder Label
        /// </summary>
        /// <value></value>
        public string Audio { get; set; }

        /// <summary>
        /// Videos Folder Label
        /// </summary>
        /// <value></value>
        public string Video { get; set; }

        /// <summary>
        /// Documents Folder Label
        /// </summary>
        /// <value></value>
        public string Document { get; set; }

        /// <summary>
        /// new Files Prefix
        /// </summary>
        /// <value></value>
        public string FilePrefix { get; set; }

        /// <summary>
        /// Thumb Files Prefix
        /// </summary>
        /// <value></value>
        public string ThumbPrefix { get; set; }

        /// <summary>
        /// Thumbnail File Sizes
        /// </summary>
        /// <value></value>
        public int ThumbSize { get; set; }

        /// <summary>
        /// Thumbnail File Quality
        /// </summary>
        /// <value></value>
        public int ThumbQuality { get; set; }

        /// <summary>
        /// Max File Size 
        /// </summary>
        /// <value></value>
        public long MaxFileSize { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Providers\XStorageProvider.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xModels.Dtos;
using xStorageService.Constants;
using xStorageService.Helpers;
using xStorageService.Interfaces;
using xStorageService.Models;

namespace xStorageService.Providers
{
    public partial class XStorageProvider : IXStorageProvider
    {

        public readonly string BasePath;
        private readonly XFileType[] ThumbSupprtedTypes = new XFileType[] {
            XFileType.Image, XFileType.CoverImage, XFileType.ProfileImasge
        };

        public IFileProvider FileProvider { get; }
        public XStorageHelper StorageHelper { get; }
        public IXThumbnailProvider ThumbnailProvider { get; }
        public XStorageConfiguration Configuration { get; }

        public XStorageProvider(
            IFileProvider fileProvider,
            XStorageHelper storageHelper,
            IXThumbnailProvider thumbnailProvider,
            XStorageConfiguration configuration
        )
        {
            //
            FileProvider = fileProvider;
            Configuration = configuration;
            StorageHelper = storageHelper;
            ThumbnailProvider = thumbnailProvider;

            //
            BasePath = Path
                .Combine(Directory
                    .GetCurrentDirectory(), Configuration.BaseFolder);
        }

        //
        #region Special Folders Path Getter (s) ...
        /// <summary>
        /// Get Storage Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetStorageFolderPath()
        {
            return Path.Combine(BasePath, Configuration.Storage);
        }

        /// <summary>
        /// Get Temp Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetTempFolderPath()
        {
            return Path.Combine(GetStorageFolderPath(), Configuration.Temp);
        }

        /// <summary>
        /// Get Uploads Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetUploadsFolderPath()
        {
            return Path.Combine(GetStorageFolderPath(), Configuration.Uploads);
        }

        /// <summary>
        /// Get Widgets Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetWidgetsFolderPath()
        {
            return Path.Combine(GetStorageFolderPath(), Configuration.Widgets);
        }

        /// <summary>
        /// Get Thumb Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetThumbFolderPath()
        {
            return Path.Combine(GetUploadsFolderPath(), Configuration.Thumb);
        }

        /// <summary>
        /// Get Images Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetImageFolderPath()
        {
            return Path.Combine(GetUploadsFolderPath(), Configuration.Image);
        }

        /// <summary>
        /// Get Audios Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetAudioFolderPath()
        {
            return Path.Combine(GetUploadsFolderPath(), Configuration.Audio);
        }

        /// <summary>
        /// Get Videos Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetVideoFolderPath()
        {
            return Path.Combine(GetUploadsFolderPath(), Configuration.Video);
        }

        /// <summary>
        /// Get Documents Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetDocumentFolderPath()
        {
            return Path.Combine(GetUploadsFolderPath(), Configuration.Document);
        }

        /// <summary>
        /// Prepare Full Path to Use for Static Files
        /// </summary>
        /// <param name="fullPath"></param>
        /// <returns></returns>
        public string FilePathResolver(string fullPath)
        {
            return fullPath.Replace(BasePath, "");
        }

        /// <summary>
        /// Convert a File Path to Url 
        /// </summary>
        /// <param name="fullPath"></param>
        /// <returns></returns>        
        public string ConvertToProfileImageUrl(string fullPath)
        {
            //
            var authority = !Configuration.IdentityAuthority.IsNullOrEmpty() &&
                Configuration.IdentityAuthority.EndsWith("/") ?
                Configuration.IdentityAuthority.Substring(0, Configuration.IdentityAuthority.Length - 1) :
                Configuration.IdentityAuthority;

            //
            return $"{authority}{FilePathResolver(fullPath)}";
        }

        /// <summary>
        /// Convert a File Path to Url 
        /// </summary>
        /// <param name="fullPath"></param>
        /// <returns></returns>        
        public string ConvertToFileUrl(string fullPath)
        {
            //
            var authority = !Configuration.Authority.IsNullOrEmpty() &&
                Configuration.Authority.EndsWith("/") ?
                Configuration.Authority.Substring(0, Configuration.Authority.Length - 1) :
                Configuration.Authority;

            //
            return $"{authority}/{FilePathResolver(fullPath)}";
        }
        #endregion

        //
        #region Prepare Storage Structure ...
        /// <summary>
        /// Check Folder Structure of Storage Area
        /// and Create them if not Exists
        /// </summary>
        public void Prepare()
        {
            //
            try
            {
                //
                // Storage Folder Path Check ...
                if (!IsFolderExists(GetStorageFolderPath()))
                {
                    Directory.CreateDirectory(GetStorageFolderPath());
                }

                //
                // Temp Folder Path Check ...
                if (!IsFolderExists(GetTempFolderPath()))
                {
                    Directory.CreateDirectory(GetTempFolderPath());
                }

                //
                // Temp Folder Path Check ...
                if (!IsFolderExists(GetThumbFolderPath()))
                {
                    Directory.CreateDirectory(GetThumbFolderPath());
                }

                //
                // Widgets Folder Path Chekc ...
                if (!IsFolderExists(GetWidgetsFolderPath()))
                {
                    Directory.CreateDirectory(GetWidgetsFolderPath());
                }

                //
                // Uploads Folder Path Chekc ...
                if (!IsFolderExists(GetUploadsFolderPath()))
                {
                    Directory.CreateDirectory(GetUploadsFolderPath());
                }

                //
                // Image Folder Path Chekc ...
                if (!IsFolderExists(GetImageFolderPath()))
                {
                    Directory.CreateDirectory(GetImageFolderPath());
                }

                //
                // Music Folder Path Chekc ...
                if (!IsFolderExists(GetAudioFolderPath()))
                {
                    Directory.CreateDirectory(GetAudioFolderPath());
                }

                //
                // Video Folder Path Chekc ...
                if (!IsFolderExists(GetVideoFolderPath()))
                {
                    Directory.CreateDirectory(GetVideoFolderPath());
                }

                //
                // Document Folder Path Chekc ...
                if (!IsFolderExists(GetDocumentFolderPath()))
                {
                    Directory.CreateDirectory(GetDocumentFolderPath());
                }
            }
            catch
            {
                XException.StorageServiceInitialFailed.Throw();
            }

            //
            // Set Temp Folder for Actions ...
            ThumbnailProvider.SetTempFolder(GetTempFolderPath());
        }
        #endregion

        //
        #region Validators ...
        /// <summary>
        /// Detrmines a Path Exists or not 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public bool IsFolderExists(string path)
        {
            return Directory.Exists(path);
        }

        /// <summary>
        /// Check a File Exists or not
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public bool IsFileExists(string filePath)
        {
            return File.Exists(filePath);
        }

        /// <summary>
        /// Check a File Name Support Thumbnail or not
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public bool IsSupportThumb(string fileName)
        {
            //
            if (!fileName.StartsWith(Configuration.FilePrefix))
            {
                XException.InavlidFile.Throw();
            }

            //
            var fileType = StorageHelper.GetType(fileName);
            return IsSupportThumb(fileType);
        }

        /// <summary>
        /// Check a FileType Support Thumbnail or not
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public bool IsSupportThumb(XFileType type)
        {
            return ThumbSupprtedTypes.Contains(type);
        }

        /// <summary>
        /// Validate a File Exists or not
        /// </summary>
        /// <param name="filePath"></param>
        public void ValidateFileExists(string filePath)
        {
            //
            if (!IsFileExists(filePath))
            {
                XException.NotFound.Throw();
            }
        }

        /// <summary>
        /// Validate a File Model with it's Related Physical File
        /// </summary>
        /// <param name="file"></param>
        public void ValidateFileModel(XFileDto file)
        {
            //
            // Validate Args ...
            if (file == null)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Full File Path ...
            var fileFullPath = file.Path;
            if (fileFullPath.IsNullOrEmpty())
            {
                XException.InavlidFile.Throw();
            }

            //
            // Retrieve is File Exists or not ...
            var isPhysicalFileExists = IsFileExists(file.Path);
            if (!isPhysicalFileExists)
            {
                XException.NotFound.Throw();
            }
        }

        /// <summary>
        /// Validate File for Upload
        /// </summary>
        /// <param name="file"></param>
        public void ValidateFile(IFormFile file)
        {
            //
            // Validate Args ...
            if (file == null)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check File Size not Zero ...
            if (file.Length == 0)
            {
                XException.EmptyFile.Throw();
            }

            //
            // Check File Max Size ...
            if (file.Length > Configuration.MaxFileSize)
            {
                XException.MaxFileSizeExceeded.Throw();
            }
        }

        /// <summary>
        /// Validate a Collection of IFormFile
        /// </summary>
        /// <param name="files"></param>
        public void ValidateFiles(IFormFileCollection files)
        {
            //
            // Validate Args ...
            if (!files.HasChild())
            {
                XException.InvalidArgs.Throw();
            }

            //
            files.ToList()
                .ForEach(f => ValidateFile(f));
        }

        /// <summary>
        /// Validate File for Profile Image
        /// </summary>
        /// <param name="file"></param>
        public void ValidateProfileImage(IFormFile file)
        {
            //
            // Check File Validation ...
            // since Args Checked in File Validation, there is no need to
            // double check it ...
            ValidateFile(file);

            //
            // Check File Type ...
            var fileType = GetFileType(file.FileName);
            if (fileType != XFileType.Image)
            {
                XException.UnsupportedFileType.Throw();
            }
        }
        #endregion

        //
        #region Generators ...
        /// <summary>
        /// Generate New File
        /// </summary>
        /// <returns></returns>
        public string NewFileName()
        {
            return Configuration.FilePrefix + Guid.NewGuid().ToString().ToLower();
        }

        /// <summary>
        /// Retrieve Related Thumnail File
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GenerateThumbName(string fileName)
        {
            //
            if (!IsSupportThumb(fileName))
            {
                XException.UnsupportedFileType.Throw();
            }

            //
            return fileName.Replace(Configuration.FilePrefix, Configuration.ThumbPrefix);
        }

        /// <summary>
        /// Get a New FileName with Extension based on Given fileName
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetNewFileName(string fileName)
        {
            //
            // Validate Args ...
            if (fileName.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var fileExt = GetFileExtension(fileName);
            var newFileNameWithoutExt = NewFileName();

            //
            // Generate New File Name ...
            var newFileName = string.Format("{0}{1}", newFileNameWithoutExt, fileExt);

            //
            return newFileName;
        }
        #endregion

        //
        #region Tools Actions ...
        /// <summary>
        /// Extract a FileName's Extension
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetFileExtension(string fileName)
        {
            //
            var result = StorageHelper.GetFileExtension(fileName);
            if (result.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Extract a FileName's Without it's Extension
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetFileNameWithoutExtension(string fileName)
        {
            //
            var result = StorageHelper.GetFileNameWithoutExtension(fileName);
            if (result.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Get file Extension of Specified File Name
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public FileExtensions GetFileExtensionType(string fileName)
        {
            //
            var fileExt = GetFileExtension(fileName);
            if (fileExt.IsNullOrEmpty())
            {
                XException.InvalidData.Throw();
            }

            //
            var result = StorageHelper.GetExtensionType(fileExt);
            if (result == -1)
            {
                XException.UnsupportedFileType.Throw();
            }

            //
            return (FileExtensions)result;
        }

        /// <summary>
        /// Return File Type of Specific File Name
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public XFileType GetFileType(string fileName)
        {
            //
            var fileExtension = GetFileExtensionType(fileName);
            return GetFileType(fileExtension);
        }

        /// <summary>
        /// Return File Type of Specific Extension
        /// </summary>
        /// <param name="fileExtension"></param>
        /// <returns></returns>
        public XFileType GetFileType(FileExtensions fileExtension)
        {
            return StorageHelper.GetType((int)fileExtension);
        }

        /// <summary>
        /// Retrieve Full Path of thumbnail File
        /// </summary>
        /// <param name="thumFileName"></param>
        /// <returns></returns>
        public string GetThumbnailFileFullPath(string thumFileName)
        {
            //
            if (!thumFileName.StartsWith(Configuration.ThumbPrefix))
            {
                XException.InavlidFile.Throw();
            }

            //
            return Path.Combine(GetThumbFolderPath(), thumFileName);
        }

        /// <summary>
        /// Retrieve a File Thumbnail Path if Supported
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetRelatedThumbnailFullPath(string fileName)
        {
            //
            var thumbName = GenerateThumbName(fileName);
            return GetThumbnailFileFullPath(thumbName);
        }

        /// <summary>
        /// Retrieve Special File Type's Folder Path
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public string GetFileTypeFolderPath(XFileType type)
        {
            //
            // Retrieve Folder Path Based on file ...
            switch (type)
            {
                case XFileType.Image:
                case XFileType.CoverImage:
                case XFileType.ProfileImasge:
                    return GetImageFolderPath();

                case XFileType.Audio:
                    return GetAudioFolderPath();

                case XFileType.Video:
                    return GetVideoFolderPath();

                case XFileType.Document:
                default:
                    return GetDocumentFolderPath();
            }
        }

        /// <summary>
        /// Retrieve a File's Folder path
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="isTemp"></param>
        /// <param name="isWidget"></param>
        /// <returns></returns>
        public string GetFileFolderPath(
            string fileName,
            bool isTemp = false,
            bool isWidget = false
        )
        {
            //
            // Validate Args ...
            if (fileName.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var fileType = GetFileType(fileName);

            //
            var folderPath = "";

            //
            // if isTemp equals true
            // ignore file type and return Temp Folder ...
            if (isTemp)
            {
                folderPath = GetTempFolderPath();
            }

            //
            // if isWidget equals true and isTemp equals false
            // ignore file type and return Widget's Folder ...
            if (isWidget && !isTemp)
            {
                folderPath = GetWidgetsFolderPath();
            }

            //
            // if both isTemp and isWidget equals false 
            // which is the default state, retrieve proper folder path
            // based on file type and return it ...
            if (!isTemp && !isWidget)
            {
                folderPath = GetFileTypeFolderPath(fileType);
            }

            //
            // Check folderPath restrict to have Value ...
            if (folderPath.IsNullOrEmpty())
            {
                XException.InvalidData.Throw();
            }

            //
            // return result ...
            return folderPath;
        }

        /// <summary>
        /// Retrieve a Full path of a File
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="isTemp"></param>
        /// <param name="isWidget"></param>
        /// <returns></returns>
        public string GetFileFullPath(
            string fileName,
            bool isTemp = false,
            bool isWidget = false
        )
        {
            //
            var folderPath = GetFileFolderPath(
                fileName,
                isTemp: isTemp,
                isWidget: isWidget
            );

            //
            if (folderPath.IsNullOrEmpty())
            {
                XException.ActionFailed.Throw();
            }

            //
            return Path.Combine(folderPath, fileName);
        }

        /// <summary>
        /// Save a File into Storage Based on it's Type
        /// </summary>
        /// <param name="file"></param>
        /// <param name="isTemp"></param>
        /// <param name="isWidget"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<string> SaveFileAsync(
            IFormFile file,
            bool isTemp = false,
            bool isWidget = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            ValidateFile(file);

            //
            // Extract and Generate required Data ...
            var fileName = GetNewFileName(file.FileName);
            var folderPath = GetFileFolderPath(file.FileName, isTemp, isWidget);
            var fileFullPath = Path.Combine(folderPath, fileName);

            //
            // Save File ...
            using (var stream = new FileStream(fileFullPath, FileMode.Create))
            {
                //
                await file.CopyToAsync(
                    stream,
                    cancellationToken
                );
            }

            //
            // Since all Required data can be Generated based on 
            // a simple file Name, there is no need to return additional 
            // data as result ...
            return fileName;
        }

        /// <summary>
        /// Delete a Physical File by Validate it's Exists
        /// </summary>
        /// <param name="fileFullPath"></param>
        /// <param name="forceFileExists"></param>
        /// <param name="exception"></param>
        public void DeleteFile(
            string fileFullPath,
            bool forceFileExists = true,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            if (!forceFileExists &&
                fileFullPath.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.NotFound.ToException();
            }

            //
            // Check File Exists ...
            var isFileExists = File.Exists(fileFullPath);
            if (forceFileExists &&
                !isFileExists)
            {
                XException.NotFound.Throw();
            }

            //
            // Handle Prevent Error when forceFileExists false
            // and File doesn't Exists ...
            if (!forceFileExists &&
                !isFileExists)
            {
                return;
            }

            //
            File.Delete(fileFullPath);
        }

        /// <summary>
        /// Remove a List of Physical Files Path 
        /// and return Un Removable Files ...
        /// </summary>
        /// <param name="fileFullPaths"></param>
        /// <param name="forceFileExists"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        public ICollection<string> DeleteFiles(
            ICollection<string> fileFullPaths,
            bool forceFileExists = true,
            Exception exception = null
        )
        {
            //
            if (exception.IsNull())
            {
                exception = XException.NotFound.ToException();
            }

            //
            var result = fileFullPaths.Where(f => !IsFileExists(GetFileFullPath(f))).ToList();
            if (forceFileExists && result.HasChild())
            {
                throw exception;
            }

            //
            var existsFile = fileFullPaths.Where(f => IsFileExists(f)).ToList();
            existsFile.ForEach(f =>
            {
                DeleteFile(
                    f,
                    forceFileExists: forceFileExists,
                    exception: exception
                );
            });

            //
            return fileFullPaths.Except(existsFile).ToList();
        }

        /// <summary>
        /// Create Thumbnail based on FileName.Ext
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task CreateThumbnail(
            string fileName,
            CancellationToken cancellationToken = default
        )
        {
            //
            if (fileName.IsNullOrEmpty())
            {
                return;
            }

            //
            await Task.Run(() =>
            {
                //
                var fileFullPath = GetFileFullPath(fileName);
                if (!IsFileExists(fileFullPath))
                {
                    XException.NotFound.Throw();
                }

                //
                var thumbFileName = GenerateThumbName(fileName);
                var thumbFullPath = GetThumbnailFileFullPath(thumbFileName);

                //
                ThumbnailProvider.ResizeImage(
                    fileFullPath,
                    thumbFullPath,
                    Configuration.ThumbSize,
                    Configuration.ThumbQuality
                );
            }, cancellationToken);
        }

        /// <summary>
        /// Create Thumbnail based on XFile model
        /// </summary>
        /// <param name="file"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task CreateThumbnail(
            XFileDto file,
            CancellationToken cancellationToken = default
        )
        {
            //
            await CreateThumbnail(
                file.Name,
                cancellationToken
            );
        }

        /// <summary>
        /// Save and Create a Thumbnail For Profile Image
        /// </summary>
        /// <param name="file"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XFileResult> HandleProfileImageSave(
            IFormFile file,
            CancellationToken cancellationToken = default
        )
        {
            //
            ValidateProfileImage(file);

            //
            var savedFileName = await SaveFileAsync(
                file,
                isTemp: false,
                isWidget: false,
                cancellationToken: cancellationToken
            );
            var thumbFileName = GenerateThumbName(savedFileName);

            //
            var savedFileFullPath = GetFileFullPath(savedFileName);
            var thumbFullPath = GetThumbnailFileFullPath(thumbFileName);

            //
            await CreateThumbnail(
                savedFileName,
                cancellationToken
            );

            //
            return new XFileResult
            {
                Name = file.Name,
                FileName = savedFileName,
                FilePath = ConvertToProfileImageUrl(savedFileFullPath),
                Thmbnail = thumbFileName,
                ThmbnailPath = ConvertToProfileImageUrl(thumbFullPath)
            };
        }

        /// <summary>
        /// Handle File Upload with Support of Thumbnails ...
        /// </summary>
        /// <param name="file"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XFileResult> HandleFileSave(
            IFormFile file,
            CancellationToken cancellationToken = default
        )
        {
            //
            ValidateFile(file);

            //
            var savedFileName = await SaveFileAsync(file, isTemp: false, isWidget: false);

            //
            var savedFileFullPath = GetFileFullPath(savedFileName);

            //
            var thumbFileName = "";
            var thumbFullPath = "";
            var fileType = GetFileType(savedFileName);
            if (fileType.IsImageKind())
            {
                //
                thumbFileName = GenerateThumbName(savedFileName);
                thumbFullPath = GetThumbnailFileFullPath(thumbFileName);

                //
                await CreateThumbnail(savedFileName);
            }

            //
            var result =
                new XFileResult
                {
                    Name = file.FileName,
                    FileName = savedFileName,
                    FilePath = ConvertToFileUrl(savedFileFullPath),
                    Thmbnail = thumbFileName,
                    ThmbnailPath = ConvertToFileUrl(thumbFullPath),
                };

            //
            return result;
        }

        /// <summary>
        /// Handle File Upload with Support of Thumbnails ...
        /// </summary>
        /// <param name="files"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XFileResult>> HandleFilesSave(
            IFormFileCollection files,
            CancellationToken cancellationToken = default
        )
        {
            //
            ValidateFiles(files);

            //
            var result = new Collection<XFileResult>();
            foreach (var file in files)
            {
                //
                var savedFileName = await SaveFileAsync(
                    file, 
                    isTemp: false, 
                    isWidget: false,
                    cancellationToken: cancellationToken
                );

                //
                var savedFileFullPath = GetFileFullPath(savedFileName);

                //
                var thumbFileName = "";
                var thumbFullPath = "";
                var fileType = GetFileType(savedFileName);
                if (fileType.IsImageKind())
                {
                    //
                    thumbFileName = GenerateThumbName(savedFileName);
                    thumbFullPath = GetThumbnailFileFullPath(thumbFileName);

                    //
                    await CreateThumbnail(
                        savedFileName,
                        cancellationToken
                    );
                }

                //
                result.Add(
                    new XFileResult
                    {
                        Name = file.FileName,
                        FileName = savedFileName,
                        FilePath = ConvertToFileUrl(savedFileFullPath),
                        Thmbnail = thumbFileName,
                        ThmbnailPath = ConvertToFileUrl(thumbFullPath),
                    });
            }

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Providers\XThumbnailProvider.cs

using ImageMagick;
using xCommons.Extensions;
using xStorageService.Interfaces;
using xStorageService.Models;

namespace xStorageService.Providers {
    public partial class XThumbnailProvider : IXThumbnailProvider {
        public void SetTempFolder (string folder) {
            MagickNET.SetTempDirectory (folder);
        }

        public XImageInfo GetImageInfo (string filePath) {
            //
            MagickImageInfo info = new MagickImageInfo (filePath);
            return info.MapConvert<XImageInfo, MagickImageInfo> ();
        }

        public void ResizeImage (
            string filePath,
            string resizedFilePath,
            int size,
            int quality
        ) {
            //
            using (var image = new MagickImage (filePath)) {
                //
                image.Resize (size, size);
                image.Strip ();
                image.Quality = quality;
                image.Write (resizedFilePath);
            }
        }
    }
}
