Initial Commit ...

This commit is contained in:
2024-01-25 04:49:52 +03:30
commit d26a1c49fd
17 changed files with 1678 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
#
# DotNet ...
bin
obj
#
# Natural Docs ...
Documentation/*
View File
+6
View File
@@ -0,0 +1,6 @@
namespace xStorageService.Constants {
public partial struct ConfigurationNodeNames {
public const string STORAGE_SERVICE_NODE_NAME = "StorageConfiguration";
}
}
+140
View File
@@ -0,0 +1,140 @@
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,
}
}
+115
View File
@@ -0,0 +1,115 @@
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.RootFolder)
);
//
// 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 ();
}
}
}
View File
+135
View File
@@ -0,0 +1,135 @@
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;
}
}
}
+102
View File
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
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);
#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
);
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);
Task CreateThumbnail (string fileName);
Task<XFileResult> HandleProfileImageSave (IFormFile file);
Task<XFileResult> HandleFileSave (IFormFile file);
Task<IEnumerable<XFileResult>> HandleFilesSave (IFormFileCollection files);
#endregion
}
}
+14
View File
@@ -0,0 +1,14 @@
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
);
}
}
+9
View File
@@ -0,0 +1,9 @@
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; }
}
}
+15
View File
@@ -0,0 +1,15 @@
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; }
}
}
+111
View File
@@ -0,0 +1,111 @@
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; }
}
}
+924
View File
@@ -0,0 +1,924 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
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>
/// <returns></returns>
public async Task<string> SaveFileAsync (
IFormFile file,
bool isTemp = false,
bool isWidget = false) {
//
// 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);
}
//
// 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>
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>
/// <returns></returns>
public async Task CreateThumbnail (string fileName) {
//
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
);
});
}
/// <summary>
/// Create Thumbnail based on XFile model
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public async Task CreateThumbnail (XFileDto file) {
//
await CreateThumbnail (file.Name);
}
// /// <summary>
// /// Create Thumbnail based on XFile model
// /// </summary>
// /// <param name="file"></param>
// /// <returns></returns>
// public async Task CreateThumbnail (XFile file) {
// //
// await CreateThumbnail (file.Name);
// }
/// <summary>
/// Save and Create a Thumbnail For Profile Image
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public async Task<XFileResult> HandleProfileImageSave (IFormFile file) {
//
ValidateProfileImage (file);
//
var savedFileName = await SaveFileAsync (file, isTemp : false, isWidget : false);
var thumbFileName = GenerateThumbName (savedFileName);
//
var savedFileFullPath = GetFileFullPath (savedFileName);
var thumbFullPath = GetThumbnailFileFullPath (thumbFileName);
//
await CreateThumbnail (savedFileName);
//
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>
/// <returns></returns>
public async Task<XFileResult> HandleFileSave (IFormFile file) {
//
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>
/// <returns></returns>
public async Task<IEnumerable<XFileResult>> HandleFilesSave (IFormFileCollection files) {
//
ValidateFiles (files);
//
var result = new Collection<XFileResult> ();
foreach (var file in files) {
//
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);
}
//
result.Add (
new XFileResult {
Name = file.FileName,
FileName = savedFileName,
FilePath = ConvertToFileUrl (savedFileFullPath),
Thmbnail = thumbFileName,
ThmbnailPath = ConvertToFileUrl (thumbFullPath),
});
}
//
return result;
}
#endregion
}
}
+34
View File
@@ -0,0 +1,34 @@
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);
}
}
}
}
+23
View File
@@ -0,0 +1,23 @@
# xStorageService
it is a Part of xDashboard Project on SaherElm IT Center which provides:
- Files Storage.
- Files Validations.
- Files Handling.
- etc.
this module has following dependencies :
- xCommons
- xModels
for configure and use this Module refer to DI.XDIHelperExtension.cs file.
## Maintainer
Hadi Khazaee asl
[https://www.saherelm.ir](https://www.saherelm.ir)
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="liget" value="https://nuget.saherelmhub.ir/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>
+35
View File
@@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Runtime Definition -->
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>xDashboard.xStorageService</PackageId>
<Version>1.0.0</Version>
<Authors>Hadi Khazaee Asl</Authors>
<Company>SaherElm IT Center</Company>
<Description>
provide File Storage/Validating/Handling and etc tools to xDashboard project.
</Description>
<!-- Icon Definition -->
<PackageIcon>icon.png</PackageIcon>
</PropertyGroup>
<!-- Icon Handling -->
<ItemGroup>
<None Include="../../Resources/Images/favicon.png" Link="icon.png" Pack="true" PackagePath="\icon.png" />
</ItemGroup>
<!-- Local Modules -->
<ItemGroup>
<PackageReference Include="xDashboard.xModels" Version="1.0.0" />
<!-- <ProjectReference Include="../xModels/xModels.csproj" /> -->
</ItemGroup>
<!-- Dependencies -->
<ItemGroup>
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="7.23.1" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0" />
</ItemGroup>
</Project>