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) ...
///
/// Get Storage Folder Path
///
///
public string GetStorageFolderPath () {
return Path.Combine (BasePath, Configuration.Storage);
}
///
/// Get Temp Folder Path
///
///
public string GetTempFolderPath () {
return Path.Combine (GetStorageFolderPath (), Configuration.Temp);
}
///
/// Get Uploads Folder Path
///
///
public string GetUploadsFolderPath () {
return Path.Combine (GetStorageFolderPath (), Configuration.Uploads);
}
///
/// Get Widgets Folder Path
///
///
public string GetWidgetsFolderPath () {
return Path.Combine (GetStorageFolderPath (), Configuration.Widgets);
}
///
/// Get Thumb Folder Path
///
///
public string GetThumbFolderPath () {
return Path.Combine (GetUploadsFolderPath (), Configuration.Thumb);
}
///
/// Get Images Folder Path
///
///
public string GetImageFolderPath () {
return Path.Combine (GetUploadsFolderPath (), Configuration.Image);
}
///
/// Get Audios Folder Path
///
///
public string GetAudioFolderPath () {
return Path.Combine (GetUploadsFolderPath (), Configuration.Audio);
}
///
/// Get Videos Folder Path
///
///
public string GetVideoFolderPath () {
return Path.Combine (GetUploadsFolderPath (), Configuration.Video);
}
///
/// Get Documents Folder Path
///
///
public string GetDocumentFolderPath () {
return Path.Combine (GetUploadsFolderPath (), Configuration.Document);
}
///
/// Prepare Full Path to Use for Static Files
///
///
///
public string FilePathResolver (string fullPath) {
return fullPath.Replace (BasePath, "");
}
///
/// Convert a File Path to Url
///
///
///
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)}";
}
///
/// Convert a File Path to Url
///
///
///
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 ...
///
/// Check Folder Structure of Storage Area
/// and Create them if not Exists
///
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 ...
///
/// Detrmines a Path Exists or not
///
///
///
public bool IsFolderExists (string path) {
return Directory.Exists (path);
}
///
/// Check a File Exists or not
///
///
///
public bool IsFileExists (string filePath) {
return File.Exists (filePath);
}
///
/// Check a File Name Support Thumbnail or not
///
///
///
public bool IsSupportThumb (string fileName) {
//
if (!fileName.StartsWith (Configuration.FilePrefix)) {
XException.InavlidFile.Throw ();
}
//
var fileType = StorageHelper.GetType (fileName);
return IsSupportThumb (fileType);
}
///
/// Check a FileType Support Thumbnail or not
///
///
///
public bool IsSupportThumb (XFileType type) {
return ThumbSupprtedTypes.Contains (type);
}
///
/// Validate a File Exists or not
///
///
public void ValidateFileExists (string filePath) {
//
if (!IsFileExists (filePath)) {
XException.NotFound.Throw ();
}
}
///
/// Validate a File Model with it's Related Physical File
///
///
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 ();
}
}
///
/// Validate File for Upload
///
///
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 ();
}
}
///
/// Validate a Collection of IFormFile
///
///
public void ValidateFiles (IFormFileCollection files) {
//
// Validate Args ...
if (!files.HasChild ()) {
XException.InvalidArgs.Throw ();
}
//
files.ToList ()
.ForEach (f => ValidateFile (f));
}
///
/// Validate File for Profile Image
///
///
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 ...
///
/// Generate New File
///
///
public string NewFileName () {
return Configuration.FilePrefix + Guid.NewGuid ().ToString ().ToLower ();
}
///
/// Retrieve Related Thumnail File
///
///
///
public string GenerateThumbName (string fileName) {
//
if (!IsSupportThumb (fileName)) {
XException.UnsupportedFileType.Throw ();
}
//
return fileName.Replace (Configuration.FilePrefix, Configuration.ThumbPrefix);
}
///
/// Get a New FileName with Extension based on Given fileName
///
///
///
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 ...
///
/// Extract a FileName's Extension
///
///
///
public string GetFileExtension (string fileName) {
//
var result = StorageHelper.GetFileExtension (fileName);
if (result.IsNullOrEmpty ()) {
XException.InvalidArgs.Throw ();
}
//
return result;
}
///
/// Extract a FileName's Without it's Extension
///
///
///
public string GetFileNameWithoutExtension (string fileName) {
//
var result = StorageHelper.GetFileNameWithoutExtension (fileName);
if (result.IsNullOrEmpty ()) {
XException.InvalidArgs.Throw ();
}
//
return result;
}
///
/// Get file Extension of Specified File Name
///
///
///
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;
}
///
/// Return File Type of Specific File Name
///
///
///
public XFileType GetFileType (string fileName) {
//
var fileExtension = GetFileExtensionType (fileName);
return GetFileType (fileExtension);
}
///
/// Return File Type of Specific Extension
///
///
///
public XFileType GetFileType (FileExtensions fileExtension) {
return StorageHelper.GetType ((int) fileExtension);
}
///
/// Retrieve Full Path of thumbnail File
///
///
///
public string GetThumbnailFileFullPath (string thumFileName) {
//
if (!thumFileName.StartsWith (Configuration.ThumbPrefix)) {
XException.InavlidFile.Throw ();
}
//
return Path.Combine (GetThumbFolderPath (), thumFileName);
}
///
/// Retrieve a File Thumbnail Path if Supported
///
///
///
public string GetRelatedThumbnailFullPath (string fileName) {
//
var thumbName = GenerateThumbName (fileName);
return GetThumbnailFileFullPath (thumbName);
}
///
/// Retrieve Special File Type's Folder Path
///
///
///
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 ();
}
}
///
/// Retrieve a File's Folder path
///
///
///
///
///
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;
}
///
/// Retrieve a Full path of a File
///
///
///
///
///
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);
}
///
/// Save a File into Storage Based on it's Type
///
///
///
public async Task 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;
}
///
/// Delete a Physical File by Validate it's Exists
///
///
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);
}
///
/// Remove a List of Physical Files Path
/// and return Un Removable Files ...
///
///
///
///
///
public ICollection DeleteFiles (
ICollection 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 ();
}
///
/// Create Thumbnail based on FileName.Ext
///
///
///
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
);
});
}
///
/// Create Thumbnail based on XFile model
///
///
///
public async Task CreateThumbnail (XFileDto file) {
//
await CreateThumbnail (file.Name);
}
// ///
// /// Create Thumbnail based on XFile model
// ///
// ///
// ///
// public async Task CreateThumbnail (XFile file) {
// //
// await CreateThumbnail (file.Name);
// }
///
/// Save and Create a Thumbnail For Profile Image
///
///
///
public async Task 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)
};
}
///
/// Handle File Upload with Support of Thumbnails ...
///
///
///
public async Task 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;
}
///
/// Handle File Upload with Support of Thumbnails ...
///
///
///
public async Task> HandleFilesSave (IFormFileCollection files) {
//
ValidateFiles (files);
//
var result = new Collection ();
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
}
}