├── .github └── workflows │ └── gitleaks.yaml ├── App_Data └── FileManager.mdf ├── CHANGELOG.md ├── Controllers ├── SQLProviderController.cs └── TestController.cs ├── EJ2SQLDataBaseProvider.csproj ├── EJ2SQLDataBaseProvider.csproj.user ├── EJ2SQLDataBaseProvider.sln ├── Models ├── Base │ ├── AccessDetails.cs │ ├── AccessPermission.cs │ ├── ErrorDetails.cs │ ├── FileDetails.cs │ ├── FileManagerDirectoryContent.cs │ ├── FileManagerParams.cs │ ├── FileManagerResponse.cs │ └── ImageSize.cs └── SQLFileProvider.cs ├── Program.cs ├── Properties └── launchSettings.json ├── README.md ├── Startup.cs ├── appsettings.Development.json ├── appsettings.json └── web.config /.github/workflows/gitleaks.yaml: -------------------------------------------------------------------------------- 1 | name: Secret Value found!! 2 | on: 3 | push: 4 | public: 5 | jobs: 6 | scan: 7 | name: gitleaks 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v3 12 | - name: Install the gitleaks 13 | run: wget https://github.com/zricethezav/gitleaks/releases/download/v8.15.2/gitleaks_8.15.2_linux_x64.tar.gz 14 | shell: pwsh 15 | - name: Extract the tar file 16 | run: tar xzvf gitleaks_8.15.2_linux_x64.tar.gz 17 | - name: Generate the report 18 | id: gitleaks 19 | run: $GITHUB_WORKSPACE/gitleaks detect -s $GITHUB_WORKSPACE -f json -r $GITHUB_WORKSPACE/leaksreport.json 20 | shell: bash 21 | continue-on-error: true 22 | - name: Setup NuGet.exe 23 | if: steps.gitleaks.outcome != 'success' 24 | uses: nuget/setup-nuget@v1 25 | with: 26 | nuget-version: latest 27 | - name: Install the dotnet 28 | if: steps.gitleaks.outcome != 'success' 29 | uses: actions/setup-dotnet@v3 30 | with: 31 | dotnet-version: '3.1.x' 32 | - name: Install the report tool packages 33 | if: steps.gitleaks.outcome != 'success' 34 | run: | 35 | nuget install "Syncfusion.Email" -source ${{ secrets.NexusFeedLink }} -ExcludeVersion 36 | dir $GITHUB_WORKSPACE/Syncfusion.Email/lib/netcoreapp3.1 37 | dotnet $GITHUB_WORKSPACE/Syncfusion.Email/lib/netcoreapp3.1/GitleaksReportMail.dll ${{ secrets.CITEAMCREDENTIALS }} "$GITHUB_REF_NAME" ${{ secrets.NETWORKCREDENTIALS }} ${{ secrets.NETWORKKEY }} "$GITHUB_WORKSPACE" ${{ secrets.ORGANIZATIONNAME }} 38 | exit 1 -------------------------------------------------------------------------------- /App_Data/FileManager.mdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SyncfusionExamples/sql-server-database-aspcore-file-provider/51d7d5e0cb4e4885566b828452d08bc23a4d35df/App_Data/FileManager.mdf -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [Unreleased] 4 | 5 | ### SQL Server DataBase File Provider 6 | 7 | #### Bug Fixes 8 | 9 | - `#174483` - The issue with "Folders order is improper while downloading the root folder from the Navigation pane" has been fixed. 10 | 11 | - `#281523` - The issue with "Access control is not properly working in search operation" has been fixed. 12 | 13 | ### SQL Server DataBase File Provider 14 | 15 | #### New Features 16 | 17 | - `#151112`, `#152443` - Support has been provided for access control. 18 | 19 | ## 18.2.44 (2020-07-06) 20 | 21 | ### SQL Server DataBase File Provider 22 | 23 | #### New Features 24 | 25 | - `#151515` - Support has been provided for upload customization. 26 | 27 | ## 17.3.14 (2019-10-04) 28 | 29 | ### SQL Server DataBase File Provider 30 | 31 | #### Bug Fixes 32 | 33 | - Issue with changing the extension type of a file while renaming operation has been fixed. 34 | 35 | - Issue with calculating file(s) or folder(s) size has been fixed. 36 | 37 | ## 17.2.28-beta (2019-06-27) 38 | 39 | ### SQL Server DataBase File Provider 40 | 41 | #### New Features 42 | 43 | - Added file provider support for SQL server database. 44 | -------------------------------------------------------------------------------- /Controllers/SQLProviderController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text.Json; 4 | using System.Text.RegularExpressions; 5 | using Microsoft.AspNetCore.Cors; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Http.Features; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.Extensions.Configuration; 10 | using Syncfusion.EJ2.FileManager.Base; 11 | using Syncfusion.EJ2.FileManager.Base.SQLFileProvider; 12 | 13 | 14 | namespace EJ2APIServices.Controllers 15 | { 16 | [Route("api/[controller]")] 17 | [EnableCors("AllowAllOrigins")] 18 | public class SQLProviderController : Controller 19 | { 20 | SQLFileProvider operation; 21 | public SQLProviderController(IConfiguration configuration) 22 | { 23 | operation = new SQLFileProvider(configuration); 24 | string connectionName = "FileManagerConnection"; 25 | string tableName = "Product"; 26 | string rootFolderID = "0"; 27 | 28 | // Validate connection name 29 | if (!Regex.IsMatch(connectionName, "^[a-zA-Z0-9_]*$")) 30 | { 31 | throw new ArgumentException("Invalid connection name"); 32 | } 33 | 34 | // Validate table name 35 | if (!Regex.IsMatch(tableName, "^[a-zA-Z0-9_]*$")) 36 | { 37 | throw new ArgumentException("Invalid table name"); 38 | } 39 | 40 | // Validate root folder ID 41 | if (!Regex.IsMatch(rootFolderID, "^[0-9]*$")) 42 | { 43 | throw new ArgumentException("Invalid root folder ID"); 44 | } 45 | 46 | //To configure the database connection, set the connection name, table name and root folder ID value by passing these values to the SetSQLConnection method. 47 | operation.SetSQLConnection(connectionName, tableName, rootFolderID); 48 | } 49 | [Route("SQLFileOperations")] 50 | public object SQLFileOperations([FromBody] FileManagerDirectoryContent args) 51 | { 52 | if ((args.Action == "delete" || args.Action == "rename") && ((args.TargetPath == null) && (args.Path == ""))) 53 | { 54 | FileManagerResponse response = new FileManagerResponse(); 55 | response.Error = new ErrorDetails { Code = "403", Message = "Restricted to modify the root folder." }; 56 | return operation.ToCamelCase(response); 57 | } 58 | 59 | switch (args.Action) 60 | { 61 | case "read": 62 | // Reads the file(s) or folder(s) from the given path. 63 | return operation.ToCamelCase(operation.GetFiles(args.Path, false, args.Data)); 64 | case "delete": 65 | // Deletes the selected file(s) or folder(s) from the given path. 66 | return operation.ToCamelCase(operation.Delete(args.Path, args.Names, args.Data)); 67 | case "details": 68 | // Gets the details of the selected file(s) or folder(s). 69 | return operation.ToCamelCase(operation.Details(args.Path, args.Names, args.Data)); 70 | case "create": 71 | // Creates a new folder in a given path. 72 | return operation.ToCamelCase(operation.Create(args.Path, args.Name, args.Data)); 73 | case "search": 74 | // Gets the list of file(s) or folder(s) from a given path based on the searched key string. 75 | return operation.ToCamelCase(operation.Search(args.Path, args.SearchString, args.ShowHiddenItems, args.CaseSensitive, args.Data)); 76 | case "rename": 77 | // Renames a file or folder. 78 | return operation.ToCamelCase(operation.Rename(args.Path, args.Name, args.NewName, false, args.Data)); 79 | case "move": 80 | // Cuts the selected file(s) or folder(s) from a path and then pastes them into a given target path. 81 | return operation.ToCamelCase(operation.Move(args.Path, args.TargetPath, args.Names, args.RenameFiles, args.TargetData, args.Data)); 82 | case "copy": 83 | // Copies the selected file(s) or folder(s) from a path and then pastes them into a given target path. 84 | return operation.ToCamelCase(operation.Copy(args.Path, args.TargetPath, args.Names, args.RenameFiles, args.TargetData, args.Data)); 85 | } 86 | return null; 87 | } 88 | 89 | // Uploads the file(s) into a specified path 90 | [Route("SQLUpload")] 91 | public IActionResult SQLUpload(string path, long size, IList uploadFiles, string action, string data) 92 | { 93 | FileManagerResponse uploadResponse; 94 | FileManagerDirectoryContent[] dataObject = new FileManagerDirectoryContent[1]; 95 | dataObject[0] = JsonSerializer.Deserialize(data); 96 | if (dataObject[0].Name == null) 97 | { 98 | var options = new JsonSerializerOptions 99 | { 100 | PropertyNamingPolicy = JsonNamingPolicy.CamelCase, 101 | }; 102 | dataObject[0] = JsonSerializer.Deserialize(data, options); 103 | } 104 | int chunkIndex = int.TryParse(HttpContext.Request.Form["chunk-index"], out int parsedChunkIndex) ? parsedChunkIndex : 0; 105 | int totalChunk = int.TryParse(HttpContext.Request.Form["total-chunk"], out int parsedTotalChunk) ? parsedTotalChunk : 0; 106 | uploadResponse = operation.Upload(path, uploadFiles, action, dataObject, size, chunkIndex, totalChunk); 107 | if (uploadResponse.Error != null) 108 | { 109 | Response.Clear(); 110 | Response.ContentType = "application/json; charset=utf-8"; 111 | Response.StatusCode = Convert.ToInt32(uploadResponse.Error.Code); 112 | Response.HttpContext.Features.Get().ReasonPhrase = uploadResponse.Error.Message; 113 | } 114 | return Content(""); 115 | } 116 | 117 | // Downloads the selected file(s) and folder(s) 118 | [Route("SQLDownload")] 119 | public IActionResult SQLDownload(string downloadInput) 120 | { 121 | var options = new JsonSerializerOptions 122 | { 123 | PropertyNamingPolicy = JsonNamingPolicy.CamelCase, 124 | }; 125 | FileManagerDirectoryContent args = JsonSerializer.Deserialize(downloadInput, options); 126 | args.Path = (args.Path); 127 | return operation.Download(args.Path, args.Names, args.Data); 128 | } 129 | 130 | // Gets the image(s) from the given path 131 | [Route("SQLGetImage")] 132 | public IActionResult SQLGetImage(FileManagerDirectoryContent args) 133 | { 134 | return operation.GetImage(args.Path, args.ParentID, args.Id, true, null, args.Data); 135 | } 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /Controllers/TestController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.Extensions.Configuration; 7 | 8 | namespace EJ2APIServices.Controllers 9 | { 10 | [Route("api/[controller]")] 11 | public class TestController : Controller 12 | { 13 | // GET api/values 14 | [HttpGet] 15 | public IEnumerable Get() 16 | { 17 | 18 | return new string[] { "value1", "value2" }; 19 | } 20 | 21 | // GET api/values/5 22 | [HttpGet("{id}")] 23 | public string Get(int id) 24 | { 25 | return "value"; 26 | } 27 | 28 | // POST api/values 29 | [HttpPost] 30 | public void Post([FromBody]string value) 31 | { 32 | } 33 | 34 | // PUT api/values/5 35 | [HttpPut("{id}")] 36 | public void Put(int id, [FromBody]string value) 37 | { 38 | } 39 | 40 | // DELETE api/values/5 41 | [HttpDelete("{id}")] 42 | public void Delete(int id) 43 | { 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /EJ2SQLDataBaseProvider.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net9.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /EJ2SQLDataBaseProvider.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | false 5 | 6 | -------------------------------------------------------------------------------- /EJ2SQLDataBaseProvider.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.539 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EJ2SQLDataBaseProvider", "EJ2SQLDataBaseProvider.csproj", "{9F6F2E64-1C52-4804-8CCF-65E44EAB9927}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {9F6F2E64-1C52-4804-8CCF-65E44EAB9927}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {9F6F2E64-1C52-4804-8CCF-65E44EAB9927}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {9F6F2E64-1C52-4804-8CCF-65E44EAB9927}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {9F6F2E64-1C52-4804-8CCF-65E44EAB9927}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {927C5FB0-7127-4EFE-AB46-F45E09492501} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Models/Base/AccessDetails.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Syncfusion.EJ2.FileManager.Base 6 | { 7 | public class AccessDetails 8 | { 9 | public string Role { get; set; } 10 | public IEnumerable AccessRules { get; set; } 11 | } 12 | 13 | public class AccessRule 14 | { 15 | public Permission Copy { get; set; } 16 | public Permission Download { get; set; } 17 | public Permission Write { get; set; } 18 | public string Id { get; set; } 19 | public Permission Read { get; set; } 20 | public string Role { get; set; } 21 | public Permission WriteContents { get; set; } 22 | public Permission Upload { get; set; } 23 | public bool IsFile { get; set; } 24 | public string Message { get; set; } 25 | } 26 | public enum Permission 27 | { 28 | Allow, 29 | Deny 30 | } 31 | } -------------------------------------------------------------------------------- /Models/Base/AccessPermission.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Syncfusion.EJ2.FileManager.Base 6 | { 7 | public class AccessPermission 8 | { 9 | /// 10 | /// Gets or sets access to copy a file or folder. 11 | /// 12 | public bool Copy { get; set; } = true; 13 | 14 | /// 15 | /// Gets or sets permission to download a file or folder. 16 | /// 17 | public bool Download { get; set; } = true; 18 | 19 | /// 20 | /// Gets or sets permission to write a file or folder. 21 | /// 22 | public bool Write { get; set; } = true; 23 | 24 | /// 25 | /// Gets or sets permission to write the content of folder. 26 | /// 27 | public bool WriteContents { get; set; } = true; 28 | 29 | /// 30 | /// Gets or sets access to read a file or folder. 31 | /// 32 | public bool Read { get; set; } = true; 33 | 34 | /// 35 | /// Gets or sets permission to upload to the folder. 36 | /// 37 | public bool Upload { get; set; } = true; 38 | 39 | /// 40 | /// Gets or sets the access message. 41 | /// 42 | public string Message { get; set; } = string.Empty; 43 | } 44 | } -------------------------------------------------------------------------------- /Models/Base/ErrorDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Syncfusion.EJ2.FileManager.Base 4 | { 5 | public class ErrorDetails 6 | { 7 | 8 | public string Code { get; set; } 9 | 10 | public string Message { get; set; } 11 | 12 | public IEnumerable FileExists { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /Models/Base/FileDetails.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace Syncfusion.EJ2.FileManager.Base 5 | { 6 | public class FileDetails 7 | { 8 | public string Name { get; set; } 9 | public string Location { get; set; } 10 | public bool IsFile { get; set; } 11 | public string Size { get; set; } 12 | public DateTime Created { get; set; } 13 | public DateTime Modified { get; set; } 14 | public bool MultipleFiles { get; set; } 15 | public AccessPermission Permission { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /Models/Base/FileManagerDirectoryContent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.AspNetCore.Http; 4 | 5 | 6 | namespace Syncfusion.EJ2.FileManager.Base 7 | { 8 | public class FileManagerDirectoryContent 9 | { 10 | public string Path { get; set; } 11 | 12 | public string Action { get; set; } 13 | 14 | public string NewName { get; set; } 15 | 16 | public string[] RenameFiles { get; set; } 17 | 18 | public string TargetPath { get; set; } 19 | 20 | public string[] Names { get; set; } 21 | 22 | public string Name { get; set; } 23 | 24 | public long Size { get; set; } 25 | 26 | public DateTime DateModified { get; set; } 27 | 28 | public FileManagerDirectoryContent TargetData { get; set; } 29 | 30 | public DateTime DateCreated { get; set; } 31 | 32 | public bool HasChild { get; set; } 33 | 34 | public bool IsFile { get; set; } 35 | 36 | public string Type { get; set; } 37 | 38 | public string Id { get; set; } 39 | 40 | public string FilterPath { get; set; } 41 | 42 | public string FilterId { get; set; } 43 | 44 | public IList UploadFiles { get; set; } 45 | 46 | public bool CaseSensitive { get; set; } 47 | 48 | public string SearchString { get; set; } 49 | 50 | public bool ShowHiddenItems { get; set; } 51 | 52 | public string IconClass { get; set; } 53 | 54 | public string NodeId { get; set; } 55 | 56 | public string ParentID { get; set; } 57 | 58 | public bool Selected { get; set; } 59 | 60 | public string Icon { get; set; } 61 | 62 | public FileManagerDirectoryContent[] Data { get; set; } 63 | 64 | public AccessPermission Permission { get; set; } 65 | } 66 | } -------------------------------------------------------------------------------- /Models/Base/FileManagerParams.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.AspNetCore.Http; 3 | 4 | 5 | namespace Syncfusion.EJ2.FileManager.Base 6 | { 7 | public class FileManagerParams 8 | { 9 | public string Name { get; set; } 10 | 11 | public string[] Names { get; set; } 12 | 13 | public string Path { get; set; } 14 | 15 | public string TargetPath { get; set; } 16 | 17 | public string NewName { get; set; } 18 | 19 | public object Date { get; set; } 20 | 21 | public IEnumerable FileUpload { get; set; } 22 | 23 | public string[] RenameFiles { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /Models/Base/FileManagerResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Syncfusion.EJ2.FileManager.Base 4 | { 5 | 6 | public class FileManagerResponse 7 | { 8 | public FileManagerDirectoryContent CWD { get; set; } 9 | 10 | public IEnumerable Files { get; set; } 11 | 12 | public ErrorDetails Error { get; set; } 13 | 14 | public FileDetails Details { get; set; } 15 | 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /Models/Base/ImageSize.cs: -------------------------------------------------------------------------------- 1 | namespace Syncfusion.EJ2.FileManager.Base 2 | { 3 | public class ImageSize 4 | { 5 | public int Height { get; set; } 6 | public int Width { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /Models/SQLFileProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Data.SqlClient; 5 | using System.Linq; 6 | using System.IO; 7 | using System.IO.Compression; 8 | using Microsoft.AspNetCore.Http; 9 | using Microsoft.AspNetCore.Mvc; 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Win32; 12 | using System.Text.Json; 13 | 14 | 15 | namespace Syncfusion.EJ2.FileManager.Base.SQLFileProvider 16 | { 17 | public class SQLFileProvider 18 | { 19 | string connectionString; 20 | string tableName; 21 | List deleteFilesId = new List(); 22 | List checkedIDs = new List(); 23 | string rootId; 24 | SqlConnection sqlConnection; 25 | IConfiguration configuration; 26 | private List folder = new List(); 27 | private List files = new List { }; 28 | private string folderEntryName = ""; 29 | private string initEntry = ""; 30 | private string previousEntryName = ""; 31 | AccessDetails AccessDetails = new AccessDetails(); 32 | private string accessMessage = string.Empty; 33 | 34 | // Sets the configuration 35 | public SQLFileProvider(IConfiguration configuration) { this.configuration = configuration; } 36 | // Initializes the SqlConnection 37 | public SqlConnection setSQLDBConnection() 38 | { 39 | string[] appPath = (Environment.CurrentDirectory).Split(new string[] { "bin" }, StringSplitOptions.None); 40 | connectionString = connectionString.Replace("|DataDirectory|", appPath[0]); 41 | return new SqlConnection(@"" + connectionString); 42 | } 43 | 44 | // Sets the SQLConnection string, table name and table id 45 | public void SetSQLConnection(string name, string sqlTableName, string tableID) 46 | { 47 | connectionString = configuration.GetConnectionString(name); 48 | tableName = sqlTableName; 49 | rootId = tableID; 50 | } 51 | 52 | public void SetRules(AccessDetails details) 53 | { 54 | this.AccessDetails = details; 55 | } 56 | private string SanitizeFileName(string fileName) 57 | { 58 | string invalidChars = "\\/:*?\"<>|"; 59 | foreach (char invalidChar in invalidChars) 60 | { 61 | fileName = fileName.Replace(invalidChar.ToString(), ""); 62 | } 63 | fileName = fileName.Trim(); 64 | return fileName; 65 | } 66 | // Reads the files from SQL table 67 | public FileManagerResponse GetFiles(string path, bool showHiddenItems, params FileManagerDirectoryContent[] data) 68 | { 69 | sqlConnection = setSQLDBConnection(); 70 | string parentID = ""; 71 | string isRoot = ""; 72 | sqlConnection.Open(); 73 | FileManagerResponse readResponse = new FileManagerResponse(); 74 | try 75 | { 76 | if (path == "/") 77 | { 78 | parentID = this.rootId; 79 | try 80 | { 81 | using (SqlCommand command = new SqlCommand("select ItemID from " + this.tableName + " where ParentID=@ParentID", sqlConnection)) 82 | { 83 | command.Parameters.AddWithValue("@ParentID", rootId); 84 | SqlDataReader reader = command.ExecuteReader(); 85 | while (reader.Read()) { isRoot = reader["ItemID"].ToString(); } 86 | } 87 | } 88 | catch (SqlException ex) { Console.WriteLine(ex.ToString()); } 89 | finally { sqlConnection.Close(); } 90 | } 91 | else 92 | { 93 | try 94 | { 95 | using (SqlCommand command = new SqlCommand("select ParentID from " + this.tableName + " where ItemID=@ItemID", sqlConnection)) 96 | { 97 | command.Parameters.AddWithValue("@ItemID", data[0].Id); 98 | SqlDataReader reader = command.ExecuteReader(); 99 | while (reader.Read()) { parentID = reader["ParentID"].ToString(); } 100 | } 101 | } 102 | catch (SqlException ex) { Console.WriteLine(ex.ToString()); } 103 | finally { sqlConnection.Close(); } 104 | } 105 | 106 | FileManagerDirectoryContent cwd = new FileManagerDirectoryContent(); 107 | List files = new List(); 108 | try 109 | { 110 | 111 | SqlConnection sqlConnection = new SqlConnection(this.connectionString); 112 | try 113 | { 114 | sqlConnection.Open(); 115 | using (SqlCommand command = new SqlCommand("select * from " + this.tableName + " where " + ((data.Length == 0) ? "ParentID=@ParentID" : "ItemID=@ItemID"), sqlConnection)) 116 | { 117 | if (data.Length == 0) 118 | { 119 | command.Parameters.AddWithValue("@ParentID", parentID); 120 | } 121 | else 122 | { 123 | command.Parameters.AddWithValue("@ItemID", data[0].Id); 124 | } 125 | SqlDataReader reader = command.ExecuteReader(); 126 | while (reader.Read()) 127 | { 128 | cwd = new FileManagerDirectoryContent 129 | { 130 | Name = reader["Name"].ToString().Trim(), 131 | Size = (long)reader["Size"], 132 | IsFile = (bool)reader["IsFile"], 133 | FilterPath = data.Length > 0 ? data[0].FilterPath : "", 134 | DateModified = (DateTime)reader["DateModified"], 135 | DateCreated = (DateTime)reader["DateCreated"], 136 | Type = GetDefaultExtension(reader["MimeType"].ToString()), 137 | Id = reader["ItemID"].ToString(), 138 | HasChild = (bool)reader["HasChild"], 139 | ParentID = reader["ParentID"].ToString(), 140 | }; 141 | string sanitizedName = SanitizeFileName(cwd.Name); 142 | AccessPermission permission = GetPermission(cwd.Id, cwd.ParentID, sanitizedName, cwd.IsFile, path); 143 | cwd.Permission = permission; 144 | } 145 | } 146 | } 147 | catch (SqlException ex) { Console.WriteLine(ex.ToString()); } 148 | finally { sqlConnection.Close(); } 149 | } 150 | catch (SqlException e) { Console.WriteLine("Error Generated. Details: " + e.ToString()); } 151 | try 152 | { 153 | sqlConnection.Open(); 154 | using (SqlCommand command = new SqlCommand("select * from " + this.tableName + " where ParentID = @ParentID", sqlConnection)) 155 | { 156 | command.Parameters.AddWithValue("@ParentID", (path == "/") ? isRoot : data[0].Id); 157 | SqlDataReader reader = command.ExecuteReader(); 158 | while (reader.Read()) 159 | { 160 | var childFiles = new FileManagerDirectoryContent 161 | { 162 | Name = reader["Name"].ToString().Trim(), 163 | Size = (long)reader["Size"], 164 | IsFile = (bool)reader["IsFile"], 165 | DateModified = (DateTime)reader["DateModified"], 166 | DateCreated = (DateTime)reader["DateCreated"], 167 | HasChild = (bool)reader["HasChild"], 168 | Type = GetDefaultExtension(reader["MimeType"].ToString()), 169 | Id = reader["ItemID"].ToString(), 170 | ParentID = reader["ParentID"].ToString(), 171 | }; 172 | 173 | AccessPermission permission = GetPermission(childFiles.Id, childFiles.ParentID, SanitizeFileName(childFiles.Name), childFiles.IsFile, path); 174 | childFiles.Permission = permission; 175 | files.Add(childFiles); 176 | } 177 | reader.Close(); 178 | cwd.FilterId = GetFilterId(cwd.Id); 179 | foreach (var file in files) 180 | { 181 | file.FilterId = GetFilterId(file.Id); 182 | file.FilterPath = data.Length != 0 ? GetFilterPath(file.Id) : "/"; 183 | } 184 | } 185 | } 186 | catch (SqlException ex) { Console.WriteLine(ex.ToString()); } 187 | finally { sqlConnection.Close(); } 188 | readResponse.Files = files; 189 | readResponse.CWD = cwd; 190 | 191 | if (cwd.Permission != null && !cwd.Permission.Read) 192 | { 193 | readResponse.Files = null; 194 | accessMessage = cwd.Permission.Message; 195 | throw new UnauthorizedAccessException("'" + cwd.Name + "' is not accessible. You need permission to perform the read action."); 196 | } 197 | return readResponse; 198 | } 199 | catch (Exception e) 200 | { 201 | ErrorDetails error = new ErrorDetails(); 202 | error.Message = e.Message.ToString(); 203 | error.Code = error.Message.Contains("is not accessible. You need permission") ? "401" : "417"; 204 | if ((error.Code == "401") && !string.IsNullOrEmpty(accessMessage)) { error.Message = accessMessage; } 205 | readResponse.Error = error; 206 | return readResponse; 207 | } 208 | } 209 | 210 | protected AccessPermission GetPermission(string id, string parentId, string name, bool isFile, string path) 211 | { 212 | AccessPermission FilePermission = new AccessPermission(); 213 | if (isFile) 214 | { 215 | if (this.AccessDetails.AccessRules == null) 216 | { 217 | return null; 218 | } 219 | string nameExtension = Path.GetExtension(name).ToLower(); 220 | AccessRule accessFileRule = new AccessRule(); 221 | foreach (AccessRule fileRule in AccessDetails.AccessRules) 222 | { 223 | if (!string.IsNullOrEmpty(fileRule.Id) && fileRule.IsFile && (fileRule.Role == null || fileRule.Role == AccessDetails.Role)) 224 | { 225 | if (id == fileRule.Id) 226 | { 227 | FilePermission = UpdateFileRules(FilePermission, fileRule, name); 228 | } 229 | else if (fileRule.Id.IndexOf("*.*") > -1) 230 | { 231 | string parentPath = fileRule.Id.Substring(0, fileRule.Id.IndexOf("*.*")); 232 | if (string.IsNullOrEmpty(parentPath)) 233 | { 234 | FilePermission = UpdateFileRules(FilePermission, fileRule, name); 235 | } 236 | else 237 | { 238 | string idValue = parentPath.Substring(0, parentPath.LastIndexOf("/")); 239 | bool isAccessId = path.Contains(idValue); 240 | if (idValue == parentId || isAccessId) 241 | { 242 | accessFileRule = UpdateFilePermission(fileRule, parentPath, id); 243 | FilePermission = UpdateFileRules(FilePermission, accessFileRule, name); 244 | } 245 | } 246 | } 247 | else if (fileRule.Id.IndexOf("*.") > -1) 248 | { 249 | string pathExtension = Path.GetExtension(fileRule.Id).ToLower(); 250 | string parentPath = fileRule.Id.Substring(0, fileRule.Id.IndexOf("*.")); 251 | if (string.IsNullOrEmpty(parentPath)) 252 | { 253 | if (pathExtension == nameExtension) 254 | { 255 | FilePermission = UpdateFileRules(FilePermission, fileRule, name); 256 | } 257 | } 258 | else 259 | { 260 | string idValue = parentPath.Substring(0, parentPath.LastIndexOf("/")); 261 | bool isAccessId = path.Contains(idValue); 262 | if ((idValue == parentId || isAccessId) && pathExtension == nameExtension) 263 | { 264 | accessFileRule = UpdateFilePermission(fileRule, parentPath, id); 265 | FilePermission = UpdateFileRules(FilePermission, accessFileRule, name); 266 | } 267 | } 268 | } 269 | } 270 | } 271 | return FilePermission; 272 | } 273 | else 274 | { 275 | AccessRule accessFolderRule = new AccessRule(); 276 | 277 | if (this.AccessDetails.AccessRules == null) 278 | { 279 | return null; 280 | } 281 | foreach (AccessRule folderRule in AccessDetails.AccessRules) 282 | { 283 | if (folderRule.Id != null && folderRule.IsFile == false && (folderRule.Role == null || folderRule.Role == AccessDetails.Role)) 284 | { 285 | if (id == folderRule.Id) 286 | { 287 | FilePermission = UpdateFolderRules(FilePermission, folderRule, name); 288 | } 289 | else if (folderRule.Id.IndexOf("*") > -1) 290 | { 291 | string parentPath = folderRule.Id.Substring(0, folderRule.Id.IndexOf("*")); 292 | if (string.IsNullOrEmpty(parentPath)) 293 | { 294 | FilePermission = UpdateFolderRules(FilePermission, folderRule, name); 295 | } 296 | else 297 | { 298 | string idValue = parentPath.Substring(0, parentPath.LastIndexOf("/")); 299 | if (idValue == parentId) 300 | { 301 | accessFolderRule = UpdateFolderPermission(folderRule, parentPath, id); 302 | FilePermission = UpdateFolderRules(FilePermission, accessFolderRule, name); 303 | } 304 | } 305 | } 306 | else if (folderRule.Id.IndexOf("/") > -1) 307 | { 308 | string idValue = folderRule.Id.Substring(0, folderRule.Id.LastIndexOf("/")); 309 | bool isAccessId = path.Contains(idValue); 310 | if (id == idValue || parentId == idValue || isAccessId) 311 | { 312 | accessFolderRule = UpdateFolderPermission(folderRule, folderRule.Id, id); 313 | FilePermission = UpdateFolderRules(FilePermission, accessFolderRule, name); 314 | } 315 | } 316 | } 317 | } 318 | return FilePermission; 319 | } 320 | } 321 | 322 | protected AccessRule UpdateFilePermission(AccessRule accessRule, string parentPath, string id) 323 | { 324 | AccessRule accessFileRule = new AccessRule(); 325 | accessFileRule.Copy = accessRule.Copy; 326 | accessFileRule.Download = accessRule.Download; 327 | accessFileRule.Write = accessRule.Write; 328 | accessFileRule.Id = parentPath + id; 329 | accessFileRule.Read = accessRule.Read; 330 | accessFileRule.Role = accessRule.Role; 331 | accessFileRule.Message = accessRule.Message; 332 | return accessFileRule; 333 | } 334 | 335 | protected AccessRule UpdateFolderPermission(AccessRule accessRule, string parentPath, string id) 336 | { 337 | AccessRule accessFolderRule = new AccessRule(); 338 | accessFolderRule.Copy = accessRule.Copy; 339 | accessFolderRule.Download = accessRule.Download; 340 | accessFolderRule.Write = accessRule.Write; 341 | accessFolderRule.WriteContents = accessRule.WriteContents; 342 | accessFolderRule.Id = parentPath + id; 343 | accessFolderRule.Read = accessRule.Read; 344 | accessFolderRule.Role = accessRule.Role; 345 | accessFolderRule.Upload = accessRule.Upload; 346 | accessFolderRule.Message = accessRule.Message; 347 | return accessFolderRule; 348 | } 349 | 350 | protected virtual AccessPermission UpdateFileRules(AccessPermission filePermission, AccessRule fileRule, string fileName) 351 | { 352 | filePermission.Copy = HasPermission(fileRule.Copy); 353 | filePermission.Download = HasPermission(fileRule.Download); 354 | filePermission.Write = HasPermission(fileRule.Write); 355 | filePermission.Read = HasPermission(fileRule.Read); 356 | filePermission.Message = string.IsNullOrEmpty(fileRule.Message) ? "'" + fileName + "' is not accessible. You need permission to perform the read action." : fileRule.Message; 357 | return filePermission; 358 | } 359 | protected virtual AccessPermission UpdateFolderRules(AccessPermission folderPermission, AccessRule folderRule, string folderName) 360 | { 361 | folderPermission.Copy = HasPermission(folderRule.Copy); 362 | folderPermission.Download = HasPermission(folderRule.Download); 363 | folderPermission.Write = HasPermission(folderRule.Write); 364 | folderPermission.WriteContents = HasPermission(folderRule.WriteContents); 365 | folderPermission.Read = HasPermission(folderRule.Read); 366 | folderPermission.Upload = HasPermission(folderRule.Upload); 367 | folderPermission.Message = string.IsNullOrEmpty(folderRule.Message) ? "'" + folderName + "' is not accessible. You need permission to perform the read action." : folderRule.Message; 368 | return folderPermission; 369 | } 370 | 371 | protected bool HasPermission(Permission rule) 372 | { 373 | return rule == Permission.Allow ? true : false; 374 | } 375 | // Creates a new folder 376 | public FileManagerResponse Create(string path, string name, params FileManagerDirectoryContent[] data) 377 | { 378 | FileManagerResponse createResponse = new FileManagerResponse(); 379 | try 380 | { 381 | FileManagerDirectoryContent createData = new FileManagerDirectoryContent(); 382 | // Validate and sanitize the Name property 383 | string sanitizedName = SanitizeFileName(data[0].Name); 384 | AccessPermission createPermission = GetPermission(data[0].Id, data[0].ParentID, sanitizedName, data[0].IsFile, path); 385 | if (createPermission != null && (!createPermission.Read || !createPermission.WriteContents)) 386 | { 387 | accessMessage = createPermission.Message; 388 | throw new UnauthorizedAccessException("'" + data[0].Name + "' is not accessible. You need permission to perform the writeContents action."); 389 | } 390 | 391 | sqlConnection = setSQLDBConnection(); 392 | try 393 | { 394 | sqlConnection.Open(); 395 | string updateQuery = "UPDATE " + this.tableName + " SET HasChild = @HasChild WHERE ItemID = @ItemID"; 396 | using (SqlCommand updatecommand = new SqlCommand(updateQuery, sqlConnection)) 397 | { 398 | updatecommand.Parameters.AddWithValue("@HasChild", true); // Assuming HasChild should be set to true 399 | updatecommand.Parameters.AddWithValue("@ItemID", data[0].Id); 400 | updatecommand.ExecuteNonQuery(); 401 | } 402 | sqlConnection.Close(); 403 | sqlConnection.Open(); 404 | string parentID = null; 405 | string selectQuery = "SELECT ParentID FROM " + this.tableName + " WHERE ItemID = @ItemID"; 406 | using (SqlCommand selectCommand = new SqlCommand(selectQuery, sqlConnection)) 407 | { 408 | selectCommand.Parameters.AddWithValue("@ItemID", data[0].Id); 409 | 410 | using (SqlDataReader reader = selectCommand.ExecuteReader()) 411 | { 412 | if (reader.Read()) 413 | { 414 | parentID = reader["ParentID"].ToString(); 415 | } 416 | } 417 | } 418 | sqlConnection.Close(); 419 | Int32 count; 420 | sqlConnection.Open(); 421 | string checkQuery = "SELECT COUNT(Name) FROM " + this.tableName + " WHERE ParentID = @ParentID AND MimeType = 'folder' AND Name = @Name"; 422 | using (SqlCommand checkCommand = new SqlCommand(checkQuery, sqlConnection)) 423 | { 424 | checkCommand.Parameters.AddWithValue("@ParentID", data[0].Id); 425 | checkCommand.Parameters.AddWithValue("@Name", name.Trim()); 426 | count = (Int32)checkCommand.ExecuteScalar(); 427 | } 428 | sqlConnection.Close(); 429 | if (count != 0) 430 | { 431 | ErrorDetails error = new ErrorDetails(); 432 | error.Code = "400"; 433 | error.Message = "A folder with the name " + name.Trim() + " already exists."; 434 | createResponse.Error = error; 435 | return createResponse; 436 | } 437 | else 438 | { 439 | sqlConnection.Open(); 440 | SqlCommand command = new SqlCommand("INSERT INTO " + tableName + " (Name, ParentID, Size, IsFile, MimeType, DateModified, DateCreated, HasChild, IsRoot, Type) VALUES ( @Name, @ParentID, @Size, @IsFile, @MimeType, @DateModified, @DateCreated, @HasChild, @IsRoot, @Type )", sqlConnection); 441 | command.Parameters.Add(new SqlParameter("@Name", name.Trim())); 442 | command.Parameters.Add(new SqlParameter("@ParentID", data[0].Id)); 443 | command.Parameters.Add(new SqlParameter("@Size", 30)); 444 | command.Parameters.Add(new SqlParameter("@IsFile", false)); 445 | command.Parameters.Add(new SqlParameter("@MimeType", "Folder")); 446 | command.Parameters.Add(new SqlParameter("@DateModified", DateTime.Now)); 447 | command.Parameters.Add(new SqlParameter("@DateCreated", DateTime.Now)); 448 | command.Parameters.Add(new SqlParameter("@HasChild", false)); 449 | command.Parameters.Add(new SqlParameter("@IsRoot", false)); 450 | command.Parameters.Add(new SqlParameter("@Type", "Folder")); 451 | command.ExecuteNonQuery(); 452 | sqlConnection.Close(); 453 | sqlConnection.Open(); 454 | string readQuery = "SELECT * FROM " + tableName + " WHERE ParentID = @ParentID AND MimeType = 'folder' AND Name = @Name"; 455 | using (SqlCommand readCommand = new SqlCommand(readQuery, sqlConnection)) 456 | { 457 | readCommand.Parameters.AddWithValue("@ParentID", data[0].Id); 458 | readCommand.Parameters.AddWithValue("@Name", name.Trim()); 459 | SqlDataReader reader = readCommand.ExecuteReader(); 460 | while (reader.Read()) 461 | { 462 | createData = new FileManagerDirectoryContent 463 | { 464 | Name = reader["Name"].ToString().Trim(), 465 | Id = reader["ItemId"].ToString().Trim(), 466 | Size = (long)reader["Size"], 467 | IsFile = (bool)reader["IsFile"], 468 | DateModified = (DateTime)reader["DateModified"], 469 | DateCreated = (DateTime)reader["DateCreated"], 470 | Type = "", 471 | HasChild = (bool)reader["HasChild"], 472 | ParentID = reader["ParentID"].ToString().Trim(), 473 | }; 474 | AccessPermission permission = GetPermission(createData.Id, createData.ParentID, SanitizeFileName(createData.Name), createData.IsFile, path); 475 | createData.Permission = permission; 476 | } 477 | reader.Close(); 478 | } 479 | } 480 | } 481 | catch (SqlException ex) { Console.WriteLine(ex.ToString()); } 482 | finally { sqlConnection.Close(); } 483 | createResponse.Files = new FileManagerDirectoryContent[] { createData }; 484 | return createResponse; 485 | } 486 | catch (Exception e) 487 | { 488 | ErrorDetails error = new ErrorDetails(); 489 | error.Message = e.Message.ToString(); 490 | error.Code = error.Message.Contains("is not accessible. You need permission") ? "401" : "417"; 491 | if ((error.Code == "401") && !string.IsNullOrEmpty(accessMessage)) { error.Message = accessMessage; } 492 | createResponse.Error = error; 493 | return createResponse; 494 | } 495 | } 496 | 497 | // Downloads file(s) and folder(s) 498 | public FileStreamResult Download(string path, string[] names, params FileManagerDirectoryContent[] data) 499 | { 500 | try 501 | { 502 | FileStreamResult fileStreamResult = null; 503 | if (data != null) 504 | { 505 | sqlConnection = setSQLDBConnection(); 506 | sqlConnection.Open(); 507 | foreach (FileManagerDirectoryContent item in data) 508 | { 509 | bool isFile = item.IsFile; 510 | string sanitizedName = SanitizeFileName(item.Name); 511 | AccessPermission permission = GetPermission(item.Id, item.ParentID, sanitizedName, isFile, path); 512 | if (permission != null && (!permission.Read || !permission.Download)) 513 | { 514 | throw new UnauthorizedAccessException("'" + item.Name + "' is not accessible. Access is denied."); 515 | } 516 | try 517 | { 518 | using (SqlCommand sqlCommand = new SqlCommand("SELECT * FROM " + tableName + " WHERE ItemId = @ItemId", sqlConnection)) 519 | { 520 | sqlCommand.Parameters.AddWithValue("@ItemId", item.Id); 521 | 522 | SqlDataReader myReader = sqlCommand.ExecuteReader(); 523 | while (myReader.Read()) 524 | { 525 | string safePath = SanitizeAndValidatePath(Path.Combine(Path.GetTempPath(), item.Name)); 526 | if (File.Exists(safePath)) 527 | File.Delete(safePath); 528 | if (item.IsFile) 529 | { 530 | using (Stream file = File.OpenWrite(safePath)) 531 | { 532 | file.Write(((byte[])myReader["Content"]), 0, ((byte[])myReader["Content"]).Length); 533 | if (files.IndexOf(item.Name) == -1) files.Add(item.Name); 534 | } 535 | } 536 | else if (files.IndexOf(item.Name) == -1) files.Add(item.Name); 537 | } 538 | myReader.Close(); 539 | } 540 | } 541 | catch (Exception) { throw; } 542 | } 543 | sqlConnection.Close(); 544 | if (files.Count == 1 && data[0].IsFile) 545 | { 546 | try 547 | { 548 | string safePath = SanitizeAndValidatePath(Path.Combine(Path.GetTempPath(), files[0])); 549 | fileStreamResult = new FileStreamResult((new FileStream(safePath, FileMode.Open, FileAccess.Read)), "APPLICATION/octet-stream"); 550 | fileStreamResult.FileDownloadName = files[0]; 551 | } 552 | catch (Exception) { throw; } 553 | } 554 | else 555 | { 556 | ZipArchiveEntry zipEntry; 557 | ZipArchive archive; 558 | var tempPath = Path.Combine(Path.GetTempPath(), "temp.zip"); 559 | try 560 | { 561 | using (archive = ZipFile.Open(tempPath, ZipArchiveMode.Update)) 562 | { 563 | for (var i = 0; i < files.Count; i++) 564 | { 565 | bool isFile = false; 566 | using (SqlCommand downloadCommand = new SqlCommand("SELECT * FROM " + tableName + " WHERE Name = @FileName", sqlConnection)) 567 | { 568 | downloadCommand.Parameters.AddWithValue("@FileName", files[i]); 569 | sqlConnection.Open(); 570 | 571 | using (SqlDataReader downloadCommandReader = downloadCommand.ExecuteReader()) 572 | { 573 | while (downloadCommandReader.Read()) 574 | { 575 | isFile = (bool)downloadCommandReader["IsFile"]; 576 | } 577 | } 578 | } 579 | sqlConnection.Close(); 580 | if (isFile) 581 | { 582 | string safePath = SanitizeAndValidatePath(Path.GetTempPath() + files[i]); 583 | zipEntry = archive.CreateEntryFromFile(safePath, files[i], CompressionLevel.Fastest); 584 | } 585 | else 586 | { 587 | sqlConnection.Open(); 588 | this.folderEntryName = files[i]; 589 | this.initEntry = files[i]; 590 | DownloadFolder(archive, files[i], sqlConnection); 591 | sqlConnection.Close(); 592 | } 593 | } 594 | archive.Dispose(); 595 | fileStreamResult = new FileStreamResult((new FileStream(tempPath, FileMode.Open, FileAccess.Read, FileShare.Delete)), "APPLICATION/octet-stream"); 596 | fileStreamResult.FileDownloadName = files.Count == 1 ? data[0].Name + ".zip" : "Files.zip"; 597 | if (File.Exists(Path.Combine(Path.GetTempPath(), "temp.zip"))) 598 | File.Delete(Path.Combine(Path.GetTempPath(), "temp.zip")); 599 | } 600 | } 601 | catch (Exception) { throw; } 602 | } 603 | } 604 | return fileStreamResult; 605 | } 606 | catch (Exception) 607 | { 608 | return null; 609 | } 610 | } 611 | 612 | public void DownloadFolder(ZipArchive archive, string subFolderName, SqlConnection sqlConnection) 613 | { 614 | LinkedList subFolders = new LinkedList(); 615 | subFolders.AddLast(subFolderName); 616 | 617 | LinkedList folderPath = new LinkedList(); 618 | folderPath.AddLast(subFolderName); 619 | 620 | while (subFolders.Any()) 621 | { 622 | subFolderName = subFolders.First(); 623 | subFolders.RemoveFirst(); 624 | string folderName = folderPath.First(); 625 | folderPath.RemoveFirst(); 626 | ZipArchiveEntry zipEntry; 627 | byte[] fileContent = null; 628 | string parentID = ""; 629 | string fileName = ""; 630 | bool isFile = false; 631 | zipEntry = archive.CreateEntry(folderName + "/"); 632 | SqlCommand readCommand = new SqlCommand("SELECT * FROM " + tableName + " WHERE Name = @SubFolderName", sqlConnection); 633 | readCommand.Parameters.AddWithValue("@SubFolderName", subFolderName); 634 | SqlDataReader readCommandReader = readCommand.ExecuteReader(); 635 | while (readCommandReader.Read()) 636 | { 637 | parentID = readCommandReader["ItemID"].ToString().Trim(); 638 | } 639 | readCommandReader.Close(); 640 | SqlCommand downloadReadCommand = new SqlCommand("SELECT * FROM " + tableName + " WHERE ParentID = @ParentID", sqlConnection); 641 | downloadReadCommand.Parameters.AddWithValue("@ParentID", parentID); 642 | SqlDataReader downloadReadCommandReader = downloadReadCommand.ExecuteReader(); 643 | while (downloadReadCommandReader.Read()) 644 | { 645 | fileName = downloadReadCommandReader["Name"].ToString().Trim(); 646 | isFile = (bool)downloadReadCommandReader["IsFile"]; 647 | if (isFile) fileContent = (byte[])downloadReadCommandReader["Content"]; 648 | if (isFile) 649 | { 650 | string safePath = SanitizeAndValidatePath(Path.Combine(Path.GetTempPath(), fileName)); 651 | if (System.IO.File.Exists(safePath)) 652 | System.IO.File.Delete(safePath); 653 | using (var file = System.IO.File.OpenWrite(safePath)) 654 | { 655 | file.Write(fileContent, 0, fileContent.Length); 656 | file.Close(); 657 | zipEntry = archive.CreateEntryFromFile(safePath, folderName + "\\" + fileName, CompressionLevel.Fastest); 658 | } 659 | if (System.IO.File.Exists(safePath)) 660 | System.IO.File.Delete(safePath); 661 | } 662 | else { folderPath.AddLast(folderName + "/" + fileName); subFolders.AddLast(fileName); } 663 | } 664 | downloadReadCommandReader.Close(); 665 | } 666 | 667 | } 668 | // Calculates the folder size 669 | public long GetFolderSize(string[] idValue) 670 | { 671 | long sizeValue = 0; 672 | sqlConnection.Open(); 673 | foreach (var id in idValue) 674 | { 675 | this.checkedIDs.Add(id); 676 | string removeQuery = "WITH cte AS (SELECT ItemID, Name, ParentID FROM " + this.tableName + " WHERE ParentID = @ParentID " + 677 | "UNION ALL SELECT p.ItemID, p.Name, p.ParentID FROM Product p INNER JOIN cte ON p.ParentID = cte.ItemID) " + 678 | "SELECT ItemID FROM cte;"; 679 | 680 | using (SqlCommand removeCommand = new SqlCommand(removeQuery, sqlConnection)) 681 | { 682 | removeCommand.Parameters.AddWithValue("@ParentID", id); 683 | 684 | using (SqlDataReader removeCommandReader = removeCommand.ExecuteReader()) 685 | { 686 | while (removeCommandReader.Read()) 687 | { 688 | this.checkedIDs.Add(removeCommandReader["ItemID"].ToString()); 689 | } 690 | } 691 | } 692 | } 693 | sqlConnection.Close(); 694 | if (this.checkedIDs.Count > 0) 695 | { 696 | sqlConnection.Open(); 697 | string query = "SELECT Size FROM " + this.tableName + " WHERE ItemID IN (" + string.Join(", ", this.checkedIDs.Select((_, i) => $"@param{i}")) + ")"; 698 | using (SqlCommand getDetailsCommand = new SqlCommand(query, sqlConnection)) 699 | { 700 | for (int i = 0; i < this.checkedIDs.Count; i++) 701 | { 702 | getDetailsCommand.Parameters.AddWithValue($"@param{i}", this.checkedIDs[i]); 703 | } 704 | using (SqlDataReader getDetailsCommandReader = getDetailsCommand.ExecuteReader()) 705 | { 706 | while (getDetailsCommandReader.Read()) 707 | { 708 | sizeValue += Convert.ToInt64(getDetailsCommandReader["Size"]); 709 | } 710 | } 711 | } 712 | sqlConnection.Close(); 713 | } 714 | this.checkedIDs = null; 715 | return sizeValue; 716 | } 717 | // Gets the details of the file(s) or folder(s) 718 | public FileManagerResponse Details(string path, string[] names, params FileManagerDirectoryContent[] data) 719 | { 720 | sqlConnection = setSQLDBConnection(); 721 | string rootDirectory = ""; 722 | bool isVariousFolders = false; 723 | string previousPath = ""; 724 | string previousName = ""; 725 | FileManagerResponse getDetailResponse = new FileManagerResponse(); 726 | FileDetails detailFiles = new FileDetails(); 727 | try 728 | { 729 | string queryString = "SELECT * FROM " + this.tableName + " WHERE ItemID = @ItemId"; 730 | string itemId = data[0].Id == null ? this.rootId : data[0].Id; 731 | bool isNamesAvailable = names.Length > 0 ? true : false; 732 | try 733 | { 734 | string sizeValue = ""; 735 | var listOfStrings = new List(); 736 | long size = 0; 737 | long folderValue = 0; 738 | if (names.Length == 0 && data.Length != 0) 739 | { 740 | List values = new List(); 741 | foreach (var item in data) { values.Add(item.Name); } 742 | names = values.ToArray(); 743 | } 744 | if (!data[0].IsFile && names.Length == 1) 745 | sizeValue = ByteConversion(GetFolderSize(new string[] { data[0].Id })); 746 | else 747 | { 748 | foreach (var item in data) 749 | { 750 | if (!item.IsFile) 751 | listOfStrings.Add(item.Id); 752 | } 753 | folderValue = listOfStrings.Count > 0 ? GetFolderSize(listOfStrings.ToArray()) : 0; 754 | } 755 | sqlConnection.Open(); 756 | string rootQuery = "select * from " + this.tableName + " where ParentId='" + this.rootId + "'"; 757 | SqlDataReader rootQueryReader = (new SqlCommand(rootQuery, sqlConnection)).ExecuteReader(); 758 | while (rootQueryReader.Read()) { rootDirectory = rootQueryReader["Name"].ToString().Trim(); } 759 | sqlConnection.Close(); 760 | sqlConnection.Open(); 761 | using (SqlCommand command = new SqlCommand(queryString, sqlConnection)) 762 | { 763 | command.Parameters.AddWithValue("@ItemId", itemId); 764 | 765 | using (SqlDataReader reader = command.ExecuteReader()) 766 | { 767 | if (names.Length == 1) 768 | { 769 | string detailsID = ""; 770 | string detailsParentId = ""; 771 | string absoluteFilePath = Path.Combine(Path.GetTempPath(), names[0]); 772 | while (reader.Read()) 773 | { 774 | detailFiles = new FileDetails 775 | { 776 | Name = reader["Name"].ToString().Trim(), 777 | IsFile = (bool)reader["IsFile"], 778 | Size = (bool)reader["IsFile"] ? ByteConversion(long.Parse((reader["Size"]).ToString())) : sizeValue, 779 | Modified = (DateTime)reader["DateModified"], 780 | Created = (DateTime)reader["DateCreated"] 781 | }; 782 | detailsID = reader["ItemID"].ToString().Trim(); 783 | detailsParentId = reader["ParentID"].ToString().Trim(); 784 | string sanitizedName = SanitizeFileName(detailFiles.Name); 785 | AccessPermission permission = GetPermission(detailsID, detailsParentId, sanitizedName, detailFiles.IsFile, path); 786 | detailFiles.Permission = permission; 787 | } 788 | reader.Close(); 789 | detailFiles.Location = (rootDirectory != detailFiles.Name) ? (rootDirectory + GetFilterPath(detailsID) + detailFiles.Name).Replace("/", @"\") : rootDirectory; 790 | } 791 | else 792 | { 793 | detailFiles = new FileDetails(); 794 | foreach (var item in data) 795 | { 796 | detailFiles.Name = string.IsNullOrEmpty(previousName) ? previousName = item.Name : previousName = previousName + ", " + item.Name; 797 | previousPath = string.IsNullOrEmpty(previousPath) ? rootDirectory + item.FilterPath : previousPath; 798 | if (previousPath == rootDirectory + item.FilterPath && !isVariousFolders) 799 | { 800 | previousPath = rootDirectory + item.FilterPath; 801 | detailFiles.Location = (rootDirectory + (item.FilterPath).Replace("/", @"\")).Substring(0, (previousPath.Length - 1)); 802 | } 803 | else 804 | { 805 | isVariousFolders = true; 806 | detailFiles.Location = "Various Folders"; 807 | } 808 | if (item.IsFile) size = size + item.Size; 809 | } 810 | detailFiles.Size = ByteConversion((long)(size + folderValue)); 811 | detailFiles.MultipleFiles = true; 812 | } 813 | } 814 | } 815 | } 816 | catch (SqlException ex) { Console.WriteLine(ex.ToString()); } 817 | finally { sqlConnection.Close(); } 818 | getDetailResponse.Details = detailFiles; 819 | return getDetailResponse; 820 | } 821 | catch (Exception e) 822 | { 823 | ErrorDetails error = new ErrorDetails(); 824 | error.Message = e.Message.ToString(); 825 | error.Code = error.Message.Contains("is not accessible. You need permission") ? "401" : "417"; 826 | getDetailResponse.Error = error; 827 | return getDetailResponse; 828 | } 829 | } 830 | // Gets the file type 831 | public static string GetDefaultExtension(string mimeType) 832 | { 833 | string result; 834 | RegistryKey key; 835 | object value; 836 | key = Registry.ClassesRoot.OpenSubKey(@"MIME\Database\Content Type\" + mimeType.Trim(), false); 837 | value = key != null ? key.GetValue("Extension", null) : null; 838 | result = value != null ? value.ToString() : string.Empty; 839 | return result; 840 | } 841 | 842 | public virtual AccessPermission GetFilePermission(string id, string parentId, string path) 843 | { 844 | string fileName = Path.GetFileName(path); 845 | return GetPermission(id, parentId, fileName, true, path); 846 | } 847 | 848 | // Returns the image 849 | public FileStreamResult GetImage(string path, string parentId, string id, bool allowCompress, ImageSize size, params FileManagerDirectoryContent[] data) 850 | { 851 | try 852 | { 853 | AccessPermission permission = GetFilePermission(id, parentId, path); 854 | if (permission != null && !permission.Read) 855 | { 856 | return null; 857 | } 858 | sqlConnection = setSQLDBConnection(); 859 | sqlConnection.Open(); 860 | string query = "SELECT * FROM " + tableName + " WHERE ItemID = @ItemId"; 861 | using (SqlCommand myCommand = new SqlCommand(query, sqlConnection)) 862 | { 863 | myCommand.Parameters.AddWithValue("@ItemId", id); 864 | 865 | using (SqlDataReader myReader = myCommand.ExecuteReader()) 866 | { 867 | while (myReader.Read()) 868 | { 869 | try 870 | { 871 | return new FileStreamResult(new MemoryStream((byte[])myReader["Content"]), "APPLICATION/octet-stream"); ; 872 | } 873 | catch (Exception) { throw; } 874 | } 875 | } 876 | } 877 | sqlConnection.Close(); 878 | return null; 879 | } 880 | catch (Exception) 881 | { 882 | return null; 883 | } 884 | } 885 | // Deletes the file(s) or folder(s) 886 | public FileManagerResponse Delete(string path, string[] names, params FileManagerDirectoryContent[] data) 887 | { 888 | FileManagerResponse remvoeResponse = new FileManagerResponse(); 889 | string ParentID = ""; 890 | try 891 | { 892 | FileManagerDirectoryContent deletedData = new FileManagerDirectoryContent(); 893 | List newData = new List(); 894 | sqlConnection = setSQLDBConnection(); 895 | foreach (FileManagerDirectoryContent file in data) 896 | { 897 | string sanitizedName = SanitizeFileName(file.Name); 898 | AccessPermission permission = GetPermission(file.Id, file.ParentID, sanitizedName, file.IsFile, path); 899 | if (permission != null && (!permission.Read || !permission.Write)) 900 | { 901 | accessMessage = permission.Message; 902 | throw new UnauthorizedAccessException("'" + file.Name + "' is not accessible. you need permission to perform the write action."); 903 | } 904 | try 905 | { 906 | sqlConnection.Open(); 907 | string query = "SELECT ParentID FROM " + this.tableName + " WHERE ItemID = @FileId"; 908 | using (SqlCommand idCommand = new SqlCommand(query, sqlConnection)) 909 | { 910 | idCommand.Parameters.AddWithValue("@FileId", file.Id); 911 | using (SqlDataReader idReader = idCommand.ExecuteReader()) 912 | { 913 | while (idReader.Read()) 914 | { 915 | ParentID = idReader["ParentID"].ToString(); 916 | } 917 | } 918 | } 919 | } 920 | catch (SqlException ex) { Console.WriteLine(ex.ToString()); } 921 | finally { sqlConnection.Close(); } 922 | try 923 | { 924 | int count; 925 | sqlConnection.Open(); 926 | string checkQuery = "SELECT COUNT(*) FROM " + this.tableName + " WHERE ParentID = @ParentID AND MimeType = 'folder' AND Name <> @FileName"; 927 | 928 | using (SqlCommand countCommand = new SqlCommand(checkQuery, sqlConnection)) 929 | { 930 | countCommand.Parameters.AddWithValue("@ParentID", ParentID); 931 | countCommand.Parameters.AddWithValue("@FileName", file.Name); 932 | 933 | count = (int)countCommand.ExecuteScalar(); 934 | } sqlConnection.Close(); 935 | if (count == 0) 936 | { 937 | sqlConnection.Open(); 938 | string updateQuery = "UPDATE " + this.tableName + " SET HasChild = 'False' WHERE ItemId = @ParentID"; 939 | using (SqlCommand updateCommand = new SqlCommand(updateQuery, sqlConnection)) 940 | { 941 | updateCommand.Parameters.AddWithValue("@ParentID", ParentID); 942 | updateCommand.ExecuteNonQuery(); 943 | } 944 | sqlConnection.Close(); 945 | } 946 | sqlConnection.Open(); 947 | string readerQuery = "SELECT * FROM " + this.tableName + " WHERE ItemID = @FileId"; 948 | using (SqlCommand command = new SqlCommand(readerQuery, sqlConnection)) 949 | { 950 | command.Parameters.AddWithValue("@FileId", file.Id); 951 | 952 | using (SqlDataReader reader = command.ExecuteReader()) 953 | { 954 | while (reader.Read()) 955 | { 956 | deletedData = new FileManagerDirectoryContent 957 | { 958 | Name = reader["Name"].ToString().Trim(), 959 | Size = (long)reader["Size"], 960 | IsFile = (bool)reader["IsFile"], 961 | DateModified = (DateTime)reader["DateModified"], 962 | DateCreated = (DateTime)reader["DateCreated"], 963 | Type = GetDefaultExtension(reader["MimeType"].ToString()), 964 | HasChild = (bool)reader["HasChild"], 965 | Id = reader["ItemID"].ToString() 966 | }; 967 | } 968 | reader.Close(); 969 | } 970 | } 971 | } 972 | catch (SqlException ex) { Console.WriteLine(ex.ToString()); } 973 | finally { sqlConnection.Close(); } 974 | try 975 | { 976 | sqlConnection.Open(); 977 | string deleteQuery = "DELETE FROM " + this.tableName + " WHERE ItemID = @FileId"; 978 | using (SqlCommand deleteCommand = new SqlCommand(deleteQuery, sqlConnection)) 979 | { 980 | deleteCommand.Parameters.AddWithValue("@FileId", file.Id); 981 | deleteCommand.ExecuteNonQuery(); 982 | } 983 | string absoluteFilePath = SanitizeAndValidatePath(Path.Combine(Path.GetTempPath(), file.Name)); 984 | var tempDirectory = new DirectoryInfo(Path.GetTempPath()); 985 | foreach (var newFileName in Directory.GetFiles(tempDirectory.ToString())) 986 | { 987 | if (newFileName.ToString() == absoluteFilePath) 988 | { 989 | File.Delete(newFileName); 990 | } 991 | 992 | } 993 | } 994 | catch (SqlException ex) { Console.WriteLine(ex.ToString()); } 995 | finally { sqlConnection.Close(); } 996 | newData.Add(deletedData); 997 | remvoeResponse.Files = newData; 998 | } 999 | sqlConnection.Open(); 1000 | string removeQuery = "WITH cte AS (SELECT ItemID, Name, ParentID FROM " + this.tableName + " WHERE ParentID = @ParentId " + 1001 | "UNION ALL SELECT p.ItemID, p.Name, p.ParentID FROM Product p INNER JOIN cte ON p.ParentID = cte.ItemID) SELECT ItemID FROM cte"; 1002 | using (SqlCommand removeCommand = new SqlCommand(removeQuery, sqlConnection)) 1003 | { 1004 | removeCommand.Parameters.AddWithValue("@ParentId", data[0].Id); 1005 | 1006 | using (SqlDataReader removeCommandReader = removeCommand.ExecuteReader()) 1007 | { 1008 | while (removeCommandReader.Read()) 1009 | { 1010 | this.deleteFilesId.Add(removeCommandReader["ItemID"].ToString()); 1011 | } 1012 | } 1013 | } 1014 | sqlConnection.Close(); 1015 | if (this.deleteFilesId.Count > 0) 1016 | { 1017 | sqlConnection.Open(); 1018 | string deleteQuery = "DELETE FROM " + this.tableName + " WHERE ItemID IN (" + string.Join(", ", deleteFilesId.Select((f, index) => "@ItemId" + index)) + ")"; 1019 | using (SqlCommand deleteCommand = new SqlCommand(deleteQuery, sqlConnection)) 1020 | { 1021 | for (int index = 0; index < deleteFilesId.Count; index++) 1022 | { 1023 | deleteCommand.Parameters.AddWithValue("@ItemId" + index, deleteFilesId[index]); 1024 | } 1025 | 1026 | deleteCommand.ExecuteNonQuery(); 1027 | } 1028 | sqlConnection.Close(); 1029 | } 1030 | this.deleteFilesId = null; 1031 | return remvoeResponse; 1032 | } 1033 | catch (Exception e) 1034 | { 1035 | ErrorDetails error = new ErrorDetails(); 1036 | error.Message = e.Message.ToString(); 1037 | error.Code = error.Message.Contains("is not accessible. You need permission") ? "401" : "417"; 1038 | if ((error.Code == "401") && !string.IsNullOrEmpty(accessMessage)) { error.Message = accessMessage; } 1039 | remvoeResponse.Error = error; 1040 | return remvoeResponse; 1041 | } 1042 | } 1043 | // Uploads the files 1044 | public virtual FileManagerResponse Upload(string path, IList uploadFiles, string action, FileManagerDirectoryContent[] data, long size = 0, int chunkIndex = 0, int totalChunk = 0) 1045 | { 1046 | FileManagerResponse uploadResponse = new FileManagerResponse(); 1047 | 1048 | try 1049 | { 1050 | string sanitizedName = SanitizeFileName(data[0].Name); 1051 | AccessPermission permission = GetPermission(data[0].Id, data[0].ParentID, sanitizedName, data[0].IsFile, path); 1052 | if (permission != null && (!permission.Read || !permission.Upload)) 1053 | { 1054 | accessMessage = permission.Message; 1055 | throw new UnauthorizedAccessException("'" + data[0].Name + "' is not accessible. You need permission to perform the upload action."); 1056 | } 1057 | List existFiles = new List(); 1058 | foreach (IFormFile file in uploadFiles) 1059 | { 1060 | if (uploadFiles != null) 1061 | { 1062 | string fileName = Path.GetFileName(file.FileName); 1063 | string absoluteFilePath = SanitizeAndValidatePath(Path.Combine(Path.GetTempPath(), fileName)); 1064 | string contentType = file.ContentType; 1065 | bool isValidChunkUpload = file.ContentType == "application/octet-stream"; 1066 | bool isExist = IsFileExist(data[0].Id, fileName, size, isValidChunkUpload); 1067 | if (action == "save") 1068 | { 1069 | if (isExist) 1070 | { 1071 | existFiles.Add(fileName); 1072 | } 1073 | else 1074 | { 1075 | if (isValidChunkUpload) 1076 | { 1077 | PerformChunkedSQLUpload(file, fileName, contentType, chunkIndex, totalChunk, data[0].Id); 1078 | } 1079 | else 1080 | { 1081 | PerformDefaultSQLUpload(file, fileName, contentType, data[0].Id); 1082 | } 1083 | } 1084 | } 1085 | else if (action == "replace") 1086 | { 1087 | FileManagerResponse detailsResponse = this.GetFiles(path, false, data); 1088 | if (System.IO.File.Exists(absoluteFilePath) || isExist) 1089 | { 1090 | System.IO.File.Delete(absoluteFilePath); 1091 | 1092 | foreach (FileManagerDirectoryContent newData in detailsResponse.Files) 1093 | { 1094 | string existingFileName = newData.Name.ToString(); 1095 | if (existingFileName == fileName) 1096 | { 1097 | this.Delete(path, null, newData); 1098 | } 1099 | } 1100 | } 1101 | if (isValidChunkUpload) 1102 | { 1103 | PerformChunkedSQLUpload(file, fileName, contentType, chunkIndex, totalChunk, data[0].Id); 1104 | } 1105 | else 1106 | { 1107 | PerformDefaultSQLUpload(file, fileName, contentType, data[0].Id); 1108 | } 1109 | } 1110 | else if (action == "keepboth") 1111 | { 1112 | string newAbsoluteFilePath = fileName; 1113 | int index = newAbsoluteFilePath.LastIndexOf("."); 1114 | if (index >= 0) 1115 | { 1116 | newAbsoluteFilePath = newAbsoluteFilePath.Substring(0, index); 1117 | } 1118 | int fileCount = 0; 1119 | while (IsFileExist(data[0].Id, newAbsoluteFilePath + (fileCount > 0 ? "(" + fileCount.ToString() + ")" + Path.GetExtension(fileName) : Path.GetExtension(fileName)), size, isValidChunkUpload)) 1120 | { 1121 | fileCount++; 1122 | } 1123 | 1124 | newAbsoluteFilePath = newAbsoluteFilePath + (fileCount > 0 ? "(" + fileCount.ToString() + ")" : "") + Path.GetExtension(fileName); 1125 | string newFileName = Path.GetFileName(newAbsoluteFilePath); 1126 | if (isValidChunkUpload) 1127 | { 1128 | PerformChunkedSQLUpload(file, newFileName, contentType, chunkIndex, totalChunk, data[0].Id); 1129 | } 1130 | else 1131 | { 1132 | PerformDefaultSQLUpload(file, newFileName, contentType, data[0].Id); 1133 | } 1134 | } 1135 | } 1136 | } 1137 | if (existFiles.Count != 0) 1138 | { 1139 | ErrorDetails error = new ErrorDetails(); 1140 | error.FileExists = existFiles; 1141 | error.Code = "400"; 1142 | error.Message = "File Already Exists"; 1143 | uploadResponse.Error = error; 1144 | } 1145 | return uploadResponse; 1146 | } 1147 | catch (Exception e) 1148 | { 1149 | ErrorDetails error = new ErrorDetails(); 1150 | error.Message = e.Message.ToString(); 1151 | error.Code = error.Message.Contains("is not accessible. You need permission") ? "401" : "417"; 1152 | if ((error.Code == "401") && !string.IsNullOrEmpty(accessMessage)) { error.Message = accessMessage; } 1153 | uploadResponse.Error = error; 1154 | return uploadResponse; 1155 | } 1156 | 1157 | } 1158 | 1159 | public void PerformDefaultSQLUpload(IFormFile file, string fileName, string contentType, string parentId) 1160 | { 1161 | try 1162 | { 1163 | byte[] fileBytes; 1164 | using (var memoryStream = new MemoryStream()) 1165 | { 1166 | file.CopyTo(memoryStream); 1167 | fileBytes = memoryStream.ToArray(); 1168 | } 1169 | UploadQuery(fileName, contentType, fileBytes, parentId); 1170 | } 1171 | catch (Exception) 1172 | { 1173 | throw; 1174 | } 1175 | } 1176 | 1177 | public void PerformChunkedSQLUpload(IFormFile file, string fileName, string contentType, int chunkIndex, int totalChunk, string parentId) 1178 | { 1179 | try 1180 | { 1181 | byte[] buffer; 1182 | 1183 | using (var memoryStream = new MemoryStream()) 1184 | { 1185 | file.CopyTo(memoryStream); 1186 | buffer = memoryStream.ToArray(); 1187 | UploadChunkToSQL(fileName, contentType, buffer, parentId, chunkIndex, totalChunk); 1188 | } 1189 | } 1190 | catch (Exception) 1191 | { 1192 | throw; 1193 | } 1194 | } 1195 | 1196 | public void UploadChunkToSQL(string fileName, string contentType, byte[] chunkData, string parentId, int chunkIndex, int totalChunks) 1197 | { 1198 | using (SqlConnection sqlConnection = setSQLDBConnection()) 1199 | { 1200 | sqlConnection.Open(); 1201 | using (SqlTransaction transaction = sqlConnection.BeginTransaction()) 1202 | { 1203 | try 1204 | { 1205 | int commandTimeout = 30; 1206 | if (chunkIndex == 0) 1207 | { 1208 | // Insert the first chunk and initialize the file record 1209 | SqlCommand insertCommand = new SqlCommand( 1210 | "INSERT INTO " + tableName + " (Name, ParentID, Size, IsFile, MimeType, Content, DateModified, DateCreated, HasChild, IsRoot, Type) " + 1211 | "VALUES (@Name, @ParentID, @Size, @IsFile, @MimeType, @Content, @DateModified, @DateCreated, @HasChild, @IsRoot, @Type)", 1212 | sqlConnection, transaction); 1213 | insertCommand.CommandTimeout = commandTimeout; 1214 | insertCommand.Parameters.AddWithValue("@Name", fileName); 1215 | insertCommand.Parameters.AddWithValue("@IsFile", true); 1216 | insertCommand.Parameters.AddWithValue("@Size", chunkData.Length); 1217 | insertCommand.Parameters.AddWithValue("@ParentId", parentId); 1218 | insertCommand.Parameters.AddWithValue("@MimeType", contentType); 1219 | insertCommand.Parameters.AddWithValue("@Content", chunkData); 1220 | insertCommand.Parameters.AddWithValue("@DateModified", DateTime.Now); 1221 | insertCommand.Parameters.AddWithValue("@DateCreated", DateTime.Now); 1222 | insertCommand.Parameters.AddWithValue("@HasChild", false); 1223 | insertCommand.Parameters.AddWithValue("@IsRoot", false); 1224 | insertCommand.Parameters.AddWithValue("@Type", "File"); 1225 | insertCommand.ExecuteNonQuery(); 1226 | } 1227 | else 1228 | { 1229 | // Append chunk data to existing record 1230 | SqlCommand updateCommand = new SqlCommand( 1231 | "UPDATE " + tableName + " SET Content = CAST(Content AS VARBINARY(MAX)) + @Content, Size = Size + @ChunkSize " + 1232 | "WHERE Name = @Name AND ParentID = @ParentID", 1233 | sqlConnection, transaction); 1234 | 1235 | updateCommand.CommandTimeout = commandTimeout; 1236 | updateCommand.Parameters.AddWithValue("@Content", chunkData); 1237 | updateCommand.Parameters.AddWithValue("@ChunkSize", chunkData.Length); 1238 | updateCommand.Parameters.AddWithValue("@Name", fileName); 1239 | updateCommand.Parameters.AddWithValue("@ParentID", parentId); 1240 | 1241 | updateCommand.ExecuteNonQuery(); 1242 | } 1243 | // Finalize file after all chunks are uploaded 1244 | if (chunkIndex == totalChunks - 1) 1245 | { 1246 | SqlCommand finalizeCommand = new SqlCommand( 1247 | "UPDATE " + tableName + " SET DateModified = @DateModified WHERE Name = @Name AND ParentID = @ParentID", 1248 | sqlConnection, transaction); 1249 | 1250 | finalizeCommand.CommandTimeout = commandTimeout; 1251 | finalizeCommand.Parameters.AddWithValue("@DateModified", DateTime.Now); 1252 | finalizeCommand.Parameters.AddWithValue("@Name", fileName); 1253 | finalizeCommand.Parameters.AddWithValue("@ParentID", parentId); 1254 | 1255 | finalizeCommand.ExecuteNonQuery(); 1256 | } 1257 | 1258 | transaction.Commit(); 1259 | } 1260 | catch (Exception) 1261 | { 1262 | transaction.Rollback(); 1263 | throw; 1264 | } 1265 | } 1266 | } 1267 | } 1268 | 1269 | public void UploadQuery(string fileName, string contentType, byte[] bytes, string parentId) 1270 | { 1271 | sqlConnection = setSQLDBConnection(); 1272 | sqlConnection.Open(); 1273 | SqlCommand command = new SqlCommand("INSERT INTO " + tableName + " (Name, ParentID, Size, IsFile, MimeType, Content, DateModified, DateCreated, HasChild, IsRoot, Type) VALUES ( @Name, @ParentID, @Size, @IsFile, @MimeType, @Content, @DateModified, @DateCreated, @HasChild, @IsRoot, @Type )", sqlConnection); 1274 | command.Parameters.Add(new SqlParameter("@Name", fileName)); 1275 | command.Parameters.Add(new SqlParameter("@IsFile", true)); 1276 | command.Parameters.Add(new SqlParameter("@Size", bytes.Length)); 1277 | command.Parameters.Add(new SqlParameter("@ParentId", parentId)); 1278 | command.Parameters.Add(new SqlParameter("@MimeType", contentType)); 1279 | command.Parameters.Add("@Content", SqlDbType.VarBinary).Value = bytes; 1280 | command.Parameters.Add(new SqlParameter("@DateModified", DateTime.Now)); 1281 | command.Parameters.Add(new SqlParameter("@DateCreated", DateTime.Now)); 1282 | command.Parameters.Add(new SqlParameter("@HasChild", false)); 1283 | command.Parameters.Add(new SqlParameter("@IsRoot", false)); 1284 | command.Parameters.Add(new SqlParameter("@Type", "File")); 1285 | command.ExecuteNonQuery(); 1286 | } 1287 | 1288 | // Renames a file or folder 1289 | public FileManagerResponse Rename(string path, string name, string newName, bool replace = false, params FileManagerDirectoryContent[] data) 1290 | { 1291 | FileManagerResponse renameResponse = new FileManagerResponse(); 1292 | try 1293 | { 1294 | string sanitizedName = SanitizeFileName(data[0].Name); 1295 | AccessPermission permission = GetPermission(data[0].Id, data[0].ParentID, sanitizedName, data[0].IsFile, path); 1296 | if (permission != null && (!permission.Read || !permission.Write)) 1297 | { 1298 | accessMessage = permission.Message; 1299 | throw new UnauthorizedAccessException("'" + data[0].Name + "' is not accessible. You need permission"); 1300 | } 1301 | 1302 | FileManagerDirectoryContent renameData = new FileManagerDirectoryContent(); 1303 | sqlConnection = setSQLDBConnection(); 1304 | try 1305 | { 1306 | sqlConnection.Open(); 1307 | string updateQuery = "UPDATE " + this.tableName + " SET Name = @NewName, DateModified = @DateModified WHERE ItemID = @ItemID"; 1308 | SqlCommand updatecommand = new SqlCommand(updateQuery, sqlConnection); 1309 | updatecommand.Parameters.AddWithValue("@NewName", newName); 1310 | updatecommand.Parameters.AddWithValue("@DateModified", DateTime.Now); 1311 | updatecommand.Parameters.AddWithValue("@ItemID", data[0].Id); 1312 | updatecommand.ExecuteNonQuery(); 1313 | sqlConnection.Close(); 1314 | if (newName.Substring(newName.LastIndexOf(".") + 1) != name.Substring(name.LastIndexOf(".") + 1)) 1315 | { 1316 | sqlConnection.Open(); 1317 | string fileExtension = Path.GetExtension(newName); 1318 | string mimeType = "application/unknown"; 1319 | using (Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(fileExtension)) 1320 | { 1321 | if (regKey != null && regKey.GetValue("Content Type") != null) 1322 | { 1323 | mimeType = regKey.GetValue("Content Type").ToString(); 1324 | } 1325 | } 1326 | string updateTypeQuery = "UPDATE " + this.tableName + " SET MimeType = @MimeType WHERE ItemID = @ItemID"; 1327 | SqlCommand updateTypeCommand = new SqlCommand(updateTypeQuery, sqlConnection); 1328 | updateTypeCommand.Parameters.AddWithValue("@MimeType", mimeType); 1329 | updateTypeCommand.Parameters.AddWithValue("@ItemID", data[0].Id); 1330 | updateTypeCommand.ExecuteNonQuery(); 1331 | sqlConnection.Close(); 1332 | } 1333 | try 1334 | { 1335 | sqlConnection.Open(); 1336 | string selectQuery = "SELECT * FROM " + this.tableName + " WHERE ItemID = @ItemId"; 1337 | SqlCommand selectCommand = new SqlCommand(selectQuery, sqlConnection); 1338 | selectCommand.Parameters.AddWithValue("@ItemId", data[0].Id); 1339 | using (SqlDataReader reader = selectCommand.ExecuteReader()) 1340 | { 1341 | while (reader.Read()) 1342 | { 1343 | renameData = new FileManagerDirectoryContent 1344 | { 1345 | Name = reader["Name"].ToString().Trim(), 1346 | Id = reader["ItemID"].ToString().Trim(), 1347 | Size = (long)reader["Size"], 1348 | FilterPath = data[0].FilterPath, 1349 | IsFile = (bool)reader["IsFile"], 1350 | DateModified = (DateTime)reader["DateModified"], 1351 | DateCreated = (DateTime)reader["DateCreated"], 1352 | Type = "", 1353 | HasChild = (bool)reader["HasChild"] 1354 | }; 1355 | 1356 | } 1357 | reader.Close(); 1358 | renameData.FilterId = GetFilterId(renameData.Id); 1359 | } 1360 | } 1361 | catch (SqlException ex) { Console.WriteLine(ex.ToString()); } 1362 | finally { sqlConnection.Close(); } 1363 | 1364 | } 1365 | catch (SqlException ex) { Console.WriteLine(ex.ToString()); } 1366 | finally { sqlConnection.Close(); } 1367 | var newData = new FileManagerDirectoryContent[] { renameData }; 1368 | renameResponse.Files = newData; 1369 | return renameResponse; 1370 | } 1371 | catch (Exception e) 1372 | { 1373 | ErrorDetails error = new ErrorDetails(); 1374 | error.Message = e.Message.ToString(); 1375 | error.Code = error.Message.Contains("is not accessible. You need permission") ? "401" : "417"; 1376 | if ((error.Code == "401") && !string.IsNullOrEmpty(accessMessage)) { error.Message = accessMessage; } 1377 | renameResponse.Error = error; 1378 | return renameResponse; 1379 | } 1380 | } 1381 | 1382 | public string GetFilterPath(string id) 1383 | { 1384 | List parents = new List(); 1385 | string idValueQuery = "SELECT ParentID FROM " + this.tableName + " WHERE ItemID = @ItemId"; 1386 | SqlCommand idValueCommand = new SqlCommand(idValueQuery, sqlConnection); 1387 | idValueCommand.Parameters.AddWithValue("@ItemId", id); 1388 | string idValue = idValueCommand.ExecuteScalar()?.ToString().Trim(); 1389 | if (!string.IsNullOrEmpty(idValue)) 1390 | { 1391 | string query = @" 1392 | WITH cte AS ( 1393 | SELECT ItemID, Name, ParentID 1394 | FROM " + this.tableName + " WHERE ItemID = @IdValue" + @" 1395 | UNION ALL 1396 | SELECT p.ItemID, p.Name, p.ParentID 1397 | FROM " + this.tableName + @" p 1398 | INNER JOIN cte ON cte.ParentID = p.ItemID 1399 | ) 1400 | SELECT Name FROM cte WHERE ParentID != 0"; 1401 | 1402 | SqlCommand queryCommand = new SqlCommand(query, sqlConnection); 1403 | queryCommand.Parameters.AddWithValue("@IdValue", idValue); 1404 | 1405 | using (SqlDataReader reader = queryCommand.ExecuteReader()) 1406 | { 1407 | while (reader.Read()) 1408 | { 1409 | parents.Add(reader["Name"].ToString().Trim()); 1410 | } 1411 | reader.Close(); 1412 | } 1413 | } 1414 | return ("/" + (parents.Count > 0 ? (string.Join("/", parents.ToArray().Reverse()) + "/") : "")); 1415 | } 1416 | 1417 | public string GetFilterId(string id) 1418 | { 1419 | List parents = new List(); 1420 | string idValueQuery = "SELECT ParentID FROM " + this.tableName + " WHERE ItemID = @ItemId"; 1421 | SqlCommand idValueCommand = new SqlCommand(idValueQuery, sqlConnection); 1422 | idValueCommand.Parameters.AddWithValue("@ItemId", id); 1423 | string idValue = idValueCommand.ExecuteScalar()?.ToString().Trim(); 1424 | if (!string.IsNullOrEmpty(idValue)) 1425 | { 1426 | string query = @" 1427 | WITH cte AS ( 1428 | SELECT ItemID, Name, ParentID 1429 | FROM " + this.tableName + " WHERE ItemID = @IdValue" + @" 1430 | UNION ALL 1431 | SELECT p.ItemID, p.Name, p.ParentID 1432 | FROM " + this.tableName + @" p 1433 | INNER JOIN cte ON cte.ParentID = p.ItemID 1434 | ) 1435 | SELECT ItemID FROM cte"; 1436 | SqlCommand queryCommand = new SqlCommand(query, sqlConnection); 1437 | queryCommand.Parameters.AddWithValue("@IdValue", idValue); 1438 | using (SqlDataReader reader = queryCommand.ExecuteReader()) 1439 | { 1440 | while (reader.Read()) 1441 | { 1442 | parents.Add(reader["ItemID"].ToString().Trim()); 1443 | } 1444 | reader.Close(); 1445 | } 1446 | } 1447 | return (string.Join("/", parents.ToArray().Reverse()) + "/"); 1448 | } 1449 | // Search for file(s) or folder(s) 1450 | public FileManagerResponse Search(string path, string searchString, bool showHiddenItems, bool caseSensitive, params FileManagerDirectoryContent[] data) 1451 | { 1452 | sqlConnection = setSQLDBConnection(); 1453 | FileManagerResponse searchResponse = new FileManagerResponse(); 1454 | try 1455 | { 1456 | if (path == null) { path = string.Empty; }; 1457 | var searchWord = searchString; 1458 | bool hasPermission = true; 1459 | FileManagerDirectoryContent searchData; 1460 | FileManagerDirectoryContent cwd = data[0]; 1461 | sqlConnection.Close(); 1462 | string sanitizedName = SanitizeFileName(cwd.Name); 1463 | AccessPermission permission = GetPermission(data[0].Id, data[0].ParentID, sanitizedName, cwd.IsFile, path); 1464 | cwd.Permission = permission; 1465 | if (cwd.Permission != null && !cwd.Permission.Read) 1466 | { 1467 | accessMessage = cwd.Permission.Message; 1468 | throw new UnauthorizedAccessException("'" + cwd.Name + "' is not accessible. You need permission to perform the read action."); 1469 | } 1470 | searchResponse.CWD = cwd; 1471 | List foundFiles = new List(); 1472 | List availableFiles = new List(); 1473 | sqlConnection.Open(); 1474 | string removeQuery = @" 1475 | WITH cte AS ( 1476 | SELECT ItemID, Name, ParentID 1477 | FROM " + this.tableName + " WHERE ParentID = @ParentId" + @" 1478 | UNION ALL 1479 | SELECT p.ItemID, p.Name, p.ParentID 1480 | FROM " + this.tableName + @" p 1481 | INNER JOIN cte ON p.ParentID = cte.ItemID 1482 | ) 1483 | SELECT ItemID FROM cte"; 1484 | SqlCommand childCommand = new SqlCommand(removeQuery, sqlConnection); 1485 | childCommand.Parameters.AddWithValue("@ParentId", data[0].Id); 1486 | using (SqlDataReader childCommandReader = childCommand.ExecuteReader()) 1487 | { 1488 | while (childCommandReader.Read()) 1489 | { 1490 | availableFiles.Add(childCommandReader["ItemID"].ToString()); 1491 | } 1492 | } 1493 | sqlConnection.Close(); 1494 | if (availableFiles.Count > 0) 1495 | { 1496 | sqlConnection.Open(); 1497 | string query = @" 1498 | SELECT * 1499 | FROM " + this.tableName + @" 1500 | WHERE Name LIKE @SearchString AND ItemID IN (" + string.Join(",", availableFiles.Select((f, index) => $"@FileId{index}")) + ")"; 1501 | SqlCommand command = new SqlCommand(query, sqlConnection); 1502 | command.Parameters.AddWithValue("@SearchString", searchString.Replace("*", "%")); 1503 | for (int i = 0; i < availableFiles.Count; i++) 1504 | { 1505 | command.Parameters.AddWithValue($"@FileId{i}", availableFiles[i]); 1506 | } 1507 | using (SqlDataReader reader = command.ExecuteReader()) 1508 | { 1509 | while (reader.Read()) 1510 | { 1511 | searchData = new FileManagerDirectoryContent 1512 | { 1513 | Name = reader["Name"].ToString().Trim(), 1514 | Size = (long)reader["Size"], 1515 | IsFile = (bool)reader["IsFile"], 1516 | DateModified = (DateTime)reader["DateModified"], 1517 | DateCreated = (DateTime)reader["DateCreated"], 1518 | Type = GetDefaultExtension(reader["MimeType"].ToString()), 1519 | HasChild = (bool)reader["HasChild"], 1520 | Id = reader["ItemId"].ToString().Trim(), 1521 | ParentID = reader["ParentID"].ToString().Trim(), 1522 | }; 1523 | AccessPermission searchPermission = GetPermission(searchData.Id, searchData.ParentID, SanitizeFileName(searchData.Name), searchData.IsFile, path); 1524 | searchData.Permission = searchPermission; 1525 | if (searchData.Name != "Products") foundFiles.Add(searchData); 1526 | } 1527 | reader.Close(); 1528 | } 1529 | for (int i = foundFiles.Count - 1; i >= 0; i--) 1530 | { 1531 | foundFiles[i].FilterPath = GetFilterPath(foundFiles[i].Id); 1532 | foundFiles[i].FilterId = GetFilterId(foundFiles[i].Id); 1533 | hasPermission = parentsHavePermission(foundFiles[i]); 1534 | if (!hasPermission) 1535 | { 1536 | foundFiles.Remove(foundFiles[i]); 1537 | } 1538 | } 1539 | } 1540 | searchResponse.Files = (IEnumerable)foundFiles; 1541 | return searchResponse; 1542 | } 1543 | catch (Exception e) 1544 | { 1545 | ErrorDetails error = new ErrorDetails(); 1546 | error.Message = e.Message.ToString(); 1547 | error.Code = error.Message.Contains("is not accessible. You need permission") ? "401" : "417"; 1548 | if ((error.Code == "401") && !string.IsNullOrEmpty(accessMessage)) { error.Message = accessMessage; } 1549 | searchResponse.Error = error; 1550 | return searchResponse; 1551 | } 1552 | finally { sqlConnection.Close(); } 1553 | } 1554 | protected virtual bool parentsHavePermission(FileManagerDirectoryContent fileDetails) 1555 | { 1556 | String[] parentPath = fileDetails.FilterId.Split('/'); 1557 | bool hasPermission = true; 1558 | for (int i = 0; i <= parentPath.Length - 3; i++) 1559 | { 1560 | AccessPermission pathPermission = GetPermission(fileDetails.ParentID, parentPath[i], SanitizeFileName(fileDetails.Name), false, fileDetails.FilterId); 1561 | if (pathPermission == null) 1562 | { 1563 | break; 1564 | } 1565 | else if (pathPermission != null && !pathPermission.Read) 1566 | { 1567 | hasPermission = false; 1568 | break; 1569 | } 1570 | } 1571 | return hasPermission; 1572 | } 1573 | 1574 | // Copies the selected folder 1575 | public void CopyFolderFiles(string[] fileId, string[] newTargetId, SqlConnection sqlConnection) 1576 | { 1577 | List fromFoldersId = new List(); 1578 | List toFoldersId = new List(); 1579 | for (var i = 0; i < fileId.Length; i++) 1580 | { 1581 | string copyQuery = @" 1582 | INSERT INTO " + tableName + @" (Name, ParentID, Size, isFile, MimeType, Content, DateModified, DateCreated, HasChild, IsRoot, Type, FilterPath) 1583 | SELECT Name, @NewTargetId, Size, isFile, MimeType, Content, DateModified, DateCreated, HasChild, IsRoot, Type, FilterPath 1584 | FROM " + tableName + @" WHERE ParentID = @FileId"; 1585 | SqlCommand copyQuerycommand = new SqlCommand(copyQuery, sqlConnection); 1586 | copyQuerycommand.Parameters.AddWithValue("@NewTargetId", newTargetId[i]); 1587 | copyQuerycommand.Parameters.AddWithValue("@FileId", fileId[i]); 1588 | copyQuerycommand.ExecuteNonQuery(); 1589 | string checkingQuery = "SELECT ItemID FROM " + tableName + " WHERE ParentID = @NewTargetId AND MimeType = 'folder'"; 1590 | SqlCommand checkingQuerycommand = new SqlCommand(checkingQuery, sqlConnection); 1591 | checkingQuerycommand.Parameters.AddWithValue("@NewTargetId", newTargetId[i]); 1592 | using (SqlDataReader checkingQuerycommandReader = checkingQuerycommand.ExecuteReader()) 1593 | { 1594 | while (checkingQuerycommandReader.Read()) 1595 | { 1596 | toFoldersId.Add(checkingQuerycommandReader["ItemID"].ToString().Trim()); 1597 | } 1598 | checkingQuerycommandReader.Close(); 1599 | } 1600 | string toCheckingQuery = "SELECT ItemID FROM " + tableName + " WHERE ParentID = @FileId AND MimeType = 'folder'"; 1601 | SqlCommand toCheckingQuerycommand = new SqlCommand(toCheckingQuery, sqlConnection); 1602 | toCheckingQuerycommand.Parameters.AddWithValue("@FileId", fileId[i]); 1603 | using (SqlDataReader toCheckingQuerycommandReader = toCheckingQuerycommand.ExecuteReader()) 1604 | { 1605 | while (toCheckingQuerycommandReader.Read()) 1606 | { 1607 | fromFoldersId.Add(toCheckingQuerycommandReader["ItemID"].ToString().Trim()); 1608 | } 1609 | toCheckingQuerycommandReader.Close(); 1610 | } 1611 | } 1612 | if (fromFoldersId.Count > 0) 1613 | CopyFolderFiles(fromFoldersId.ToArray(), toFoldersId.ToArray(), sqlConnection); 1614 | } 1615 | // Gets the last inserted value 1616 | public string GetLastInsertedValue() 1617 | { 1618 | string getIdQuery = "SELECT SCOPE_IDENTITY()"; 1619 | SqlCommand copyQuerycommand = new SqlCommand(getIdQuery, sqlConnection); 1620 | return copyQuerycommand.ExecuteScalar().ToString().Trim(); 1621 | } 1622 | // Copies the selected file(s) or folder(s) 1623 | public FileManagerResponse Copy(string path, string targetPath, string[] names, string[] replacedItemNames, FileManagerDirectoryContent targetData, params FileManagerDirectoryContent[] data) 1624 | { 1625 | List files = new List(); 1626 | List checkingId = new List(); 1627 | sqlConnection = setSQLDBConnection(); 1628 | FileManagerResponse copyResponse = new FileManagerResponse(); 1629 | try 1630 | { 1631 | sqlConnection.Open(); 1632 | string checkingQuery = @" 1633 | WITH cte AS ( 1634 | SELECT ItemID, Name, ParentID 1635 | FROM " + this.tableName + " WHERE ParentID = @ParentId" + @" 1636 | UNION ALL 1637 | SELECT p.ItemID, p.Name, p.ParentID 1638 | FROM " + this.tableName + @" p 1639 | INNER JOIN cte ON p.ParentID = cte.ItemID 1640 | ) 1641 | SELECT ItemID FROM cte"; 1642 | SqlCommand copyCheckCommand = new SqlCommand(checkingQuery, sqlConnection); 1643 | copyCheckCommand.Parameters.AddWithValue("@ParentId", data[0].Id); 1644 | using (SqlDataReader copyCheckCommandReader = copyCheckCommand.ExecuteReader()) 1645 | { 1646 | while (copyCheckCommandReader.Read()) 1647 | { 1648 | checkingId.Add(copyCheckCommandReader["ItemID"].ToString()); 1649 | } 1650 | } 1651 | sqlConnection.Close(); 1652 | 1653 | string sanitizedName = SanitizeFileName(data[0].Name); 1654 | AccessPermission permission = GetPermission(data[0].Id, data[0].ParentID, sanitizedName, data[0].IsFile, path); 1655 | if (permission != null && (!permission.Read || !permission.WriteContents)) 1656 | { 1657 | accessMessage = permission.Message; 1658 | throw new UnauthorizedAccessException("'" + data[0].Name + "' is not accessible. You need permission to perform the copy action."); 1659 | } 1660 | if (checkingId.IndexOf(targetData.Id) != -1) 1661 | { 1662 | ErrorDetails error = new ErrorDetails(); 1663 | error.Code = "400"; 1664 | error.Message = "The destination folder is the subfolder of the source folder."; 1665 | copyResponse.Error = error; 1666 | return copyResponse; 1667 | } 1668 | foreach (var item in data) 1669 | { 1670 | try 1671 | { 1672 | sqlConnection.Open(); 1673 | List foldersId = new List(); 1674 | List lastInsertedItemId = new List(); 1675 | string lastId = ""; 1676 | string copyQuery = @" 1677 | INSERT INTO " + tableName + @" (Name, ParentID, Size, isFile, MimeType, Content, DateModified, DateCreated, HasChild, IsRoot, Type, FilterPath) 1678 | OUTPUT INSERTED.ItemID 1679 | SELECT Name, @TargetId, Size, isFile, MimeType, Content, DateModified, DateCreated, HasChild, IsRoot, Type, FilterPath 1680 | FROM " + tableName + @" WHERE ItemID = @ItemId"; 1681 | SqlCommand copyQuerycommand = new SqlCommand(copyQuery, sqlConnection); 1682 | copyQuerycommand.Parameters.AddWithValue("@TargetId", targetData.Id); 1683 | copyQuerycommand.Parameters.AddWithValue("@ItemId", item.Id); 1684 | object result = copyQuerycommand.ExecuteScalar(); 1685 | if (result != null) 1686 | { 1687 | lastId = result.ToString(); 1688 | } 1689 | else 1690 | { 1691 | throw new Exception("Failed to retrieve the last inserted ID."); 1692 | } 1693 | sqlConnection.Close(); 1694 | sqlConnection.Open(); 1695 | string query = "SELECT * FROM " + this.tableName + " WHERE ItemID = @LastId"; 1696 | SqlCommand command = new SqlCommand(query, sqlConnection); 1697 | command.Parameters.AddWithValue("@LastId", lastId); 1698 | 1699 | SqlDataReader reader = command.ExecuteReader(); 1700 | while (reader.Read()) 1701 | { 1702 | var copyFiles = new FileManagerDirectoryContent 1703 | { 1704 | Name = reader["Name"].ToString().Trim(), 1705 | Size = (long)reader["Size"], 1706 | IsFile = (bool)reader["IsFile"], 1707 | DateModified = DateTime.Now, 1708 | DateCreated = DateTime.Now, 1709 | HasChild = (bool)reader["HasChild"], 1710 | FilterPath = targetData.FilterPath + "/" + targetData.Name + "/", 1711 | Type = GetDefaultExtension(reader["MimeType"].ToString()), 1712 | Id = reader["ItemID"].ToString() 1713 | }; 1714 | if (!copyFiles.IsFile) 1715 | { 1716 | foldersId.Add(item.Id); 1717 | lastInsertedItemId.Add(lastId); 1718 | } 1719 | files.Add(copyFiles); 1720 | } 1721 | reader.Close(); 1722 | foreach (var file in files) { file.FilterId = GetFilterId(file.Id); } 1723 | if (foldersId.Count > 0) 1724 | CopyFolderFiles(foldersId.ToArray(), lastInsertedItemId.ToArray(), sqlConnection); 1725 | } 1726 | catch (Exception) 1727 | { 1728 | throw; 1729 | } 1730 | finally { sqlConnection.Close(); } 1731 | } 1732 | copyResponse.Files = files; 1733 | return copyResponse; 1734 | } 1735 | catch (Exception e) 1736 | { 1737 | ErrorDetails error = new ErrorDetails(); 1738 | error.Message = e.Message.ToString(); 1739 | error.Code = error.Message.Contains("is not accessible. You need permission") ? "401" : "417"; 1740 | if ((error.Code == "401") && !string.IsNullOrEmpty(accessMessage)) { error.Message = accessMessage; } 1741 | copyResponse.Error = error; 1742 | return copyResponse; 1743 | } 1744 | } 1745 | 1746 | public virtual string[] GetFolderDetails(string path) 1747 | { 1748 | string[] str_array = path.Split('/'), fileDetails = new string[2]; 1749 | string parentPath = ""; 1750 | for (int i = 0; i < str_array.Length - 2; i++) 1751 | { 1752 | parentPath += str_array[i] + "/"; 1753 | } 1754 | fileDetails[0] = parentPath; 1755 | fileDetails[1] = str_array[str_array.Length - 2]; 1756 | return fileDetails; 1757 | } 1758 | 1759 | // Moves the selected file(s) or folder(s) to target path 1760 | public FileManagerResponse Move(string path, string targetPath, string[] names, string[] replacedItemNames, FileManagerDirectoryContent targetData, params FileManagerDirectoryContent[] data) 1761 | { 1762 | List files = new List(); 1763 | sqlConnection = setSQLDBConnection(); 1764 | FileManagerResponse moveResponse = new FileManagerResponse(); 1765 | try 1766 | { 1767 | List checkingId = new List(); 1768 | sqlConnection.Open(); 1769 | string checkingQuery = @" 1770 | WITH cte AS ( 1771 | SELECT ItemID, Name, ParentID 1772 | FROM " + this.tableName + " WHERE ParentID = @ParentId" + @" 1773 | UNION ALL 1774 | SELECT p.ItemID, p.Name, p.ParentID 1775 | FROM " + this.tableName + @" p 1776 | INNER JOIN cte ON p.ParentID = cte.ItemID 1777 | ) 1778 | SELECT ItemID FROM cte"; 1779 | SqlCommand moveCheckCommand = new SqlCommand(checkingQuery, sqlConnection); 1780 | moveCheckCommand.Parameters.AddWithValue("@ParentId", data[0].Id); 1781 | using (SqlDataReader moveCheckCommandReader = moveCheckCommand.ExecuteReader()) 1782 | { 1783 | while (moveCheckCommandReader.Read()) 1784 | { 1785 | checkingId.Add(moveCheckCommandReader["ItemID"].ToString()); 1786 | } 1787 | } 1788 | sqlConnection.Close(); 1789 | string sanitizedName = SanitizeFileName(data[0].Name); 1790 | AccessPermission permission = GetPermission(data[0].Id, data[0].ParentID, sanitizedName, data[0].IsFile, path); 1791 | if (permission != null && (!permission.Read || !permission.WriteContents)) 1792 | { 1793 | accessMessage = permission.Message; 1794 | throw new UnauthorizedAccessException("'" + data[0].Name + "' is not accessible. You need permission to perform the write action."); 1795 | } 1796 | 1797 | if (checkingId.IndexOf(targetData.Id) != -1) 1798 | { 1799 | ErrorDetails error = new ErrorDetails(); 1800 | error.Code = "400"; 1801 | error.Message = "The destination folder is the subfolder of the source folder."; 1802 | moveResponse.Error = error; 1803 | return moveResponse; 1804 | } 1805 | foreach (var item in data) 1806 | { 1807 | sqlConnection.Open(); 1808 | try 1809 | { 1810 | string moveQuery = "UPDATE " + tableName + " SET ParentID = @TargetId WHERE ItemID = @ItemId"; 1811 | SqlCommand moveQuerycommand = new SqlCommand(moveQuery, sqlConnection); 1812 | moveQuerycommand.Parameters.AddWithValue("@TargetId", targetData.Id); 1813 | moveQuerycommand.Parameters.AddWithValue("@ItemId", item.Id); 1814 | moveQuerycommand.ExecuteNonQuery(); 1815 | sqlConnection.Close(); 1816 | sqlConnection.Open(); 1817 | string detailsQuery = "SELECT * FROM " + tableName + " WHERE ItemID = @ItemId"; 1818 | SqlCommand detailQuerycommand = new SqlCommand(detailsQuery, sqlConnection); 1819 | detailQuerycommand.Parameters.AddWithValue("@ItemId", item.Id); 1820 | SqlDataReader reader = detailQuerycommand.ExecuteReader(); 1821 | while (reader.Read()) 1822 | { 1823 | var moveFiles = new FileManagerDirectoryContent 1824 | { 1825 | Name = reader["Name"].ToString().Trim(), 1826 | Size = (long)reader["Size"], 1827 | IsFile = (bool)reader["IsFile"], 1828 | DateModified = DateTime.Now, 1829 | DateCreated = DateTime.Now, 1830 | HasChild = (bool)reader["HasChild"], 1831 | FilterPath = targetData.FilterPath + "/" + targetData.Name + "/", 1832 | Type = GetDefaultExtension(reader["MimeType"].ToString()), 1833 | Id = reader["ItemID"].ToString() 1834 | }; 1835 | files.Add(moveFiles); 1836 | } 1837 | reader.Close(); 1838 | foreach (var file in files) { file.FilterId = GetFilterId(file.Id); } 1839 | 1840 | // Update HasChild for parent and target directories 1841 | UpdateHasChildProperty(item.ParentID); 1842 | UpdateHasChildProperty(targetData.Id); 1843 | } 1844 | catch (Exception) { throw; } 1845 | finally { sqlConnection.Close(); } 1846 | } 1847 | moveResponse.Files = files; 1848 | return moveResponse; 1849 | } 1850 | catch (Exception e) 1851 | { 1852 | ErrorDetails error = new ErrorDetails(); 1853 | error.Message = e.Message.ToString(); 1854 | error.Code = e.Message.ToString().Contains("is not accessible. You need permission") ? "401" : "417"; 1855 | if ((error.Code == "401") && !string.IsNullOrEmpty(accessMessage)) { error.Message = accessMessage; } 1856 | moveResponse.Error = error; 1857 | return moveResponse; 1858 | } 1859 | } 1860 | 1861 | private void UpdateHasChildProperty(string directoryId) 1862 | { 1863 | using (SqlConnection sqlConnection = new SqlConnection(this.connectionString)) 1864 | { 1865 | try 1866 | { 1867 | sqlConnection.Open(); 1868 | // Check if the directory contains any folders 1869 | string checkFoldersQuery = "SELECT COUNT(*) FROM " + tableName + " WHERE ParentID = @ParentId AND IsFile = 0"; 1870 | SqlCommand checkFoldersCommand = new SqlCommand(checkFoldersQuery, sqlConnection); 1871 | checkFoldersCommand.Parameters.AddWithValue("@ParentId", directoryId); 1872 | int folderCount = (int)checkFoldersCommand.ExecuteScalar(); 1873 | 1874 | // Update HasChild property 1875 | string updateHasChildQuery = "UPDATE " + tableName + " SET HasChild = @HasChild WHERE ItemID = @ItemId"; 1876 | SqlCommand updateHasChildCommand = new SqlCommand(updateHasChildQuery, sqlConnection); 1877 | updateHasChildCommand.Parameters.AddWithValue("@HasChild", folderCount > 0); 1878 | updateHasChildCommand.Parameters.AddWithValue("@ItemId", directoryId); 1879 | updateHasChildCommand.ExecuteNonQuery(); 1880 | } 1881 | catch (SqlException ex) 1882 | { 1883 | Console.WriteLine(ex.ToString()); 1884 | } 1885 | finally 1886 | { 1887 | sqlConnection.Close(); 1888 | } 1889 | } 1890 | } 1891 | 1892 | // Converts the byte value to the appropriate size value 1893 | public String ByteConversion(long fileSize) 1894 | { 1895 | try 1896 | { 1897 | string[] index = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; // Longs run out around EB 1898 | if (fileSize == 0) return "0 " + index[0]; 1899 | int loc = Convert.ToInt32(Math.Floor(Math.Log(Math.Abs(fileSize), 1024))); 1900 | return (Math.Sign(fileSize) * Math.Round(Math.Abs(fileSize) / Math.Pow(1024, loc), 1)).ToString() + " " + index[loc]; 1901 | } 1902 | catch (Exception) { throw; } 1903 | } 1904 | 1905 | /// 1906 | /// Checks whether a file with the specified name exists within the specified parent folder. 1907 | /// 1908 | /// The ID of the parent folder to search within. 1909 | /// The name of the file to search for. 1910 | /// 'True' if an item with the specified name exists within the specified parent folder, otherwise 'false'. 1911 | public bool IsFileExist(string parentId, string name, long size, bool isChunk) 1912 | { 1913 | using (SqlConnection sqlConnection = setSQLDBConnection()) 1914 | { 1915 | sqlConnection.Open(); 1916 | SqlCommand checkCommand; 1917 | if (isChunk) 1918 | { 1919 | checkCommand = new SqlCommand( 1920 | "SELECT COUNT(Name) FROM " + tableName + " WHERE ParentID = @ParentID AND IsFile = 'true' AND Name = @Name AND Size = @Size", 1921 | sqlConnection 1922 | ); 1923 | checkCommand.Parameters.AddWithValue("@Size", size); 1924 | } 1925 | else 1926 | { 1927 | checkCommand = new SqlCommand( 1928 | "SELECT COUNT(Name) FROM " + tableName + " WHERE ParentID = @ParentID AND IsFile = 'true' AND Name = @Name", 1929 | sqlConnection 1930 | ); 1931 | } 1932 | checkCommand.Parameters.AddWithValue("@ParentID", parentId); 1933 | checkCommand.Parameters.AddWithValue("@Name", name.Trim()); 1934 | int count = (int)checkCommand.ExecuteScalar(); 1935 | return count != 0; 1936 | } 1937 | } 1938 | 1939 | public string ToCamelCase(FileManagerResponse userData) 1940 | { 1941 | JsonSerializerOptions options = new JsonSerializerOptions 1942 | { 1943 | PropertyNamingPolicy = JsonNamingPolicy.CamelCase, 1944 | }; 1945 | 1946 | return JsonSerializer.Serialize(userData, options); 1947 | } 1948 | 1949 | private string SanitizeAndValidatePath(string path) 1950 | { 1951 | if (string.IsNullOrWhiteSpace(path)) 1952 | { 1953 | throw new ArgumentException("Path cannot be null or empty."); 1954 | } 1955 | string decodedPath; 1956 | do 1957 | { 1958 | decodedPath = path; 1959 | path = Uri.UnescapeDataString(decodedPath); 1960 | } while (decodedPath != path); 1961 | string fullPath = Path.GetFullPath(path); 1962 | 1963 | // Ensure the path is within the allowed directory 1964 | string allowedDirectory = Path.GetFullPath(Path.GetTempPath()); 1965 | if (!fullPath.StartsWith(allowedDirectory, StringComparison.OrdinalIgnoreCase)) 1966 | { 1967 | throw new UnauthorizedAccessException("Access to the path is not allowed."); 1968 | } 1969 | 1970 | return fullPath; 1971 | } 1972 | } 1973 | } 1974 | 1975 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace EJ2FileManagerService 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | CreateWebHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:62869/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "launchUrl": "api/test", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "EJ2FileManagerService": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "launchUrl": "api/test", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | }, 26 | "applicationUrl": "http://localhost:62870/" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SQL server database file provider for Essential JS2 File Manager 2 | 3 | This repository contains the SQL server database file provider in ASP.NET Core for the Syncfusion File Manager component. 4 | 5 | To know more about SQL server database file system provider for File Manager, please refer our documentation [here] 6 | (https://ej2.syncfusion.com/aspnetcore/documentation/file-manager/file-system-provider#sql-database-file-system-provider). 7 | 8 | ## Key Features 9 | 10 | The SQL FILESTREAM feature provides efficient storage, management, and streaming of unstructured data stored as files on the file system. 11 | 12 | The SQL server database file provider serves the file system support for the FileManager component in SQL server database. 13 | 14 | The following actions can be performed with the SQL server database file provider. 15 | 16 | | **Actions** | **Description** | 17 | | --- | --- | 18 | | Read | Read the files from SQL table. | 19 | | Details | Gets a file's details which consists of Type, Size, Location and Modified date. | 20 | | Download | Downloads the selected file or folder from the SQL table. | 21 | | Upload | Uploads a file to the SQL table. It accepts uploaded media with the following characteristics:
  • Maximum file size: 30MB
  • Accepted Media MIME types: `*/*`
| 22 | | Create | Creates a New folder. | 23 | | Delete | Deletes a folder or file. | 24 | | Copy | Copys the selected Files from target. | 25 | | Move | Pastes the copied files to the desired location. | 26 | | Rename | Renames a folder or file. | 27 | | Search | Full-text queries perform linguistic searches against text data in full-text indexes by operating on words and phrases. | 28 | 29 | ## Prerequisites 30 | 31 | * Visual Studio 2022 32 | 33 | Make the SQL server connection with SQL database file ([App_Data/FileManager.mdf](https://github.com/SyncfusionExamples/sql-server-database-aspcore-file-provider/tree/master/App_Data)) and specify the connection string in "Web.config" file as specified in below code example. 34 | 35 | ``` 36 | 37 | 38 | 39 | ``` 40 | 41 | Also need to add the entry for the connection string in the [`appsettings.json`](https://github.com/SyncfusionExamples/sql-server-database-aspcore-file-provider/blob/master/appsettings.json) file as specified in below code example. 42 | 43 | ``` 44 | 45 | { 46 | "ConnectionStrings": { 47 | "FileManagerConnection": "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\App_Data\\FileManager.mdf;Integrated Security=True;Connect Timeout=30" 48 | } 49 | } 50 | 51 | ``` 52 | 53 | To configure the SQL server database connection use the `SetSQLConnection` method to set the connection name, table name and rootId of the table. 54 | 55 | ``` 56 | 57 | SetSQLConnection(string name, string tableName, string tableID) 58 | 59 | ``` 60 | 61 | ## How to run the project 62 | 63 | * Checkout this project to a location in your disk. 64 | * Open the solution file using Visual Studio 2022. 65 | * Restore the NuGet packages by rebuilding the solution. 66 | * Run the project. 67 | 68 | ## File Manager AjaxSettings 69 | 70 | To access the basic actions such as Read, Delete, Copy, Move, Rename, Search, and Get Details of File Manager using the SQL server database file provider service, just map the following code snippet in the Ajaxsettings property of File Manager. 71 | 72 | Here, the `hostUrl` will be your locally hosted port number. 73 | 74 | ``` 75 | var hostUrl = http://localhost:62870/; 76 | ajaxSettings: { 77 | url: hostUrl + 'api/SQLProvider/SQLFileOperations' 78 | } 79 | ``` 80 | 81 | ## File download AjaxSettings 82 | 83 | To perform download operation, initialize the `downloadUrl` property in ajaxSettings of the File Manager component. 84 | 85 | ``` 86 | var hostUrl = http://localhost:62870/; 87 | ajaxSettings: { 88 | url: hostUrl + 'api/SQLProvider/SQLFileOperations', 89 | downloadUrl: hostUrl + 'api/SQLProvider/SQLDownload' 90 | } 91 | ``` 92 | 93 | ## File upload AjaxSettings 94 | 95 | To perform upload operation, initialize the `uploadUrl` property in ajaxSettings of the File Manager component. 96 | 97 | ``` 98 | var hostUrl = http://localhost:62870/; 99 | ajaxSettings: { 100 | url: hostUrl + 'api/SQLProvider/SQLFileOperations', 101 | uploadUrl: hostUrl + 'api/SQLProvider/SQLUpload' 102 | } 103 | ``` 104 | 105 | ## File image preview AjaxSettings 106 | 107 | To perform image preview support in the File Manager component, initialize the `getImageUrl` property in ajaxSettings of the File Manager component. 108 | 109 | ``` 110 | var hostUrl = http://localhost:62870/; 111 | ajaxSettings: { 112 | url: hostUrl + 'api/SQLProvider/SQLFileOperations', 113 | getImageUrl: hostUrl + 'api/SQLProvider/SQLGetImage' 114 | } 115 | ``` 116 | 117 | The FileManager will be rendered as the following. 118 | 119 | ![File Manager](https://ej2.syncfusion.com/products/images/file-manager/readme.gif) 120 | 121 | 122 | ## Support 123 | 124 | Product support is available for through following mediums. 125 | 126 | * Creating incident in Syncfusion [Direct-trac](https://www.syncfusion.com/support/directtrac/incidents?utm_source=npm&utm_campaign=filemanager) support system or [Community forum](https://www.syncfusion.com/forums/essential-js2?utm_source=npm&utm_campaign=filemanager). 127 | * New [GitHub issue](https://github.com/syncfusion/ej2-javascript-ui-controls/issues/new). 128 | * Ask your query in [Stack Overflow](https://stackoverflow.com/?utm_source=npm&utm_campaign=filemanager) with tag `syncfusion` and `ej2`. 129 | 130 | ## License 131 | 132 | Check the license detail [here](https://github.com/syncfusion/ej2-javascript-ui-controls/blob/master/license). 133 | 134 | ## Changelog 135 | 136 | Check the changelog [here](https://github.com/syncfusion/ej2-javascript-ui-controls/blob/master/controls/filemanager/CHANGELOG.md) 137 | 138 | Copyright 2023 Syncfusion, Inc. All Rights Reserved. The Syncfusion Essential Studio license and copyright applies to this distribution. -------------------------------------------------------------------------------- /Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.HttpsPolicy; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Hosting; 12 | using Microsoft.Extensions.Logging; 13 | using Microsoft.Extensions.Options; 14 | 15 | namespace EJ2FileManagerService 16 | { 17 | public class Startup 18 | { 19 | public IWebHostEnvironment Environment { get; } 20 | public Startup(IConfiguration configuration, IWebHostEnvironment environment) 21 | { 22 | Configuration = configuration; 23 | Environment = environment; 24 | } 25 | 26 | public IConfiguration Configuration { get; } 27 | 28 | // This method gets called by the runtime. Use this method to add services to the container. 29 | public void ConfigureServices(IServiceCollection services) 30 | { 31 | services.AddMvc(); 32 | services.AddCors(options => 33 | { 34 | options.AddPolicy("AllowAllOrigins", builder => 35 | { 36 | builder.AllowAnyOrigin() 37 | .AllowAnyMethod() 38 | .AllowAnyHeader(); 39 | }); 40 | }); 41 | } 42 | 43 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 44 | public void Configure(IApplicationBuilder app) 45 | { 46 | if (Environment.IsDevelopment()) 47 | { 48 | app.UseDeveloperExceptionPage(); 49 | } 50 | else 51 | { 52 | app.UseHsts(); 53 | } 54 | app.UseRouting(); 55 | app.UseCors("AllowAllOrigins"); 56 | app.UseHttpsRedirection(); 57 | app.UseEndpoints(endpoints => { 58 | endpoints.MapControllerRoute(name: "default", pattern: "{controller=Test}/{action=Index}/{id?}"); 59 | }); 60 | 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "FileManagerConnection": "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\App_Data\\FileManager.mdf;Integrated Security=True;Connect Timeout=30" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Warning" 8 | } 9 | }, 10 | "AllowedHosts": "*" 11 | } 12 | 13 | -------------------------------------------------------------------------------- /web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | --------------------------------------------------------------------------------