Singe File ASPX File Browser
HTML
Website
jQuery
DataTables
Put the .aspx file in a folder on your website and it will show all the files in a folder like a file browser. The file table uses Bootstrap 5 to show the files in a table.
When you use the filename "Default.aspx", you can show the contents of a folder directly like www.yourwebsite.com/files
, but you can rename it to like "Browser.aspx". Then the url will be www.yourwebsite.com/files/browser.aspx
Comes with some configurable options like:
- Enable / disable the display and browsing of subfolders
- View the files in a DataTable.
- Enable / disable the Breadcrumb path or table footer.
- Easily changable texts to your own language.
- Specify which files are allowed and which folders are blocked.
Options
Option | Description | Default |
---|---|---|
BrowseSubFolders |
Allows the browsing of subfolders. | True |
ShowBreadCrumbs |
Show the Breadcrumb path above the file table. | True |
ShowFooter |
Show the footer with a summary of size and number of files. | True |
ShowSizeInMb |
Shows the size of files in MB instead of KB. | False |
UseDataTables |
Use DataTable for column sorting, searching and more. | True |
UseDataTablesSearch |
Enables easy searching of items in the file table. | True |
AllowedFileTypes |
Edit this list to add or remove allowed file types to be shown in the file table. | |
BlockedFolders |
Edit this list to add or remove folders from the blocked list. |
Live demo
Code Snippets
<%@ Page Language="C#" %> <%@ Import Namespace="System.IO" %> <script runat="server" type="text/C#"> //variables for various options bool BrowseSubFolders = true; bool ShowBreadCrumbs = true; bool ShowFooter = true; bool ShowSizeInMb = false; bool UseDataTables = true; bool UseDataTablesSearch = true; //localizable texts string TxtColumnFileName = "FileName"; string TxtColumnDate = "Date"; string TxtColumnType = "Type"; string TxtColumnSize = "Size"; string TxtFolderUp = ". . ."; string TxtRoot = "root"; string TxtCurrentFolder = "Current folder"; string TxtFooter = "{0:N0} files found with a total size of {1:N1} {2}."; string TxtDatatableEmpty = "No files found in the current folder."; string TxtDatatableSearch = "Search"; string TxtDatatableNohits = "No matching files found."; string TxtSizeKb = "kb"; string TxtSizeMb = "mb"; //allowed file types List<string> AllowedFileTypes = new List<string>() { ".ai", ".bmp", ".eps", ".gif", ".jpg", ".jpeg", ".png", ".psd", ".svg", ".7z", ".csv", ".doc", ".docx", ".flac", ".mp3", ".mp4", ".pdf", ".ppt", ".pptx", ".rar", ".txt", ".xls", ".xlsx", ".xml", ".zip" }; //blocked folder names List<string> BlockedFolders = new List<string>() { "bin" }; //some variables string RootFolder; string RootFolderNav; string CurrentFolder; string ParentFolder; string DownloadLinkPrefix; decimal SizeDivider; bool IsSubFolder; List<FileInfo> AllFiles; List<DirectoryInfo> AllFolders; //executed on page load protected void Page_Load(object sender, EventArgs e) { string RequestPath = Request.CurrentExecutionFilePath; string QueryString = ""; //find the root folder of the browser RootFolder = RequestPath.Replace(RequestPath.Split('/').Last(), "").TrimEnd('/'); //if this filename is not default.aspx include it in the url for folder navigation if (!RequestPath.ToLower().EndsWith("/default.aspx")) { RootFolderNav = RequestPath; } else { RootFolderNav = RootFolder; } //what is the current folder CurrentFolder = "/"; //is there a querystirng if (Request.QueryString["folder"] != null && Request.QueryString["folder"].ToString().Length > 0) { QueryString = Request.QueryString["folder"].TrimStart('/').TrimEnd('/').Trim(); CurrentFolder = CurrentFolder + QueryString; DownloadLinkPrefix = RootFolder + CurrentFolder + "/"; IsSubFolder = true; } else { DownloadLinkPrefix = RootFolder + "/"; } //if the folder does not exist or is it blocked, then redirect to base url if (!Directory.Exists(Server.MapPath(RootFolder + CurrentFolder)) || BlockedFolders.Any(x => x.ToLower() == QueryString.ToLower())) { Response.Redirect(RootFolderNav); } //get the current folder info var di = new DirectoryInfo(Server.MapPath(RootFolder + CurrentFolder)); //find all the files AllFiles = di.GetFiles("*", SearchOption.TopDirectoryOnly) .Where(x => AllowedFileTypes.Any(y => y.ToLower() == Path.GetExtension(x.Name).ToLower())) .OrderBy(y => y.Name).ToList(); //find all the folders if (BrowseSubFolders) { AllFolders = di.GetDirectories() .Where(x => !BlockedFolders.Any(y => y.ToLower() == x.Name.ToLower())) .OrderBy(y => y.Name).ToList(); } //which size to display SizeDivider = 1024; if (ShowSizeInMb) { SizeDivider = SizeDivider * SizeDivider; } //create the parent folder link if (IsSubFolder) { string LastPart = CurrentFolder.Split('/').Last(); if (!string.IsNullOrEmpty(LastPart)) { ParentFolder = CurrentFolder.Replace(LastPart, "").TrimEnd('/'); } } } </script> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"> <title>VDWWD FileBrowser - <%= CurrentFolder %></title> </head> <body> <!-- van der Waal Webdesign --> <!-- https://www.vanderwaal.eu --> <div class="container mt-3 mb-3"> <!-- breadcrumb path --> <% if ((UseDataTables && UseDataTablesSearch) || (BrowseSubFolders && ShowBreadCrumbs)) { %> <div class="row mb-3"> <div class="col-12 col-md-9 col-xxl-10 h5"> <% if (BrowseSubFolders && ShowBreadCrumbs) { %> <div class="float-start fw-bold pe-2"><%= TxtCurrentFolder %>:</div> <nav class="float-start" aria-label="breadcrumb"> <ol class="breadcrumb "> <% if (IsSubFolder) { %> <li class="breadcrumb-item"><a class="text-decoration-none" href="<%= RootFolderNav %>"><%= TxtRoot %></a></li> <% var folders = CurrentFolder.Split('/').Skip(1).ToList(); for (int i = 0; i < folders.Count(); i++) { if (CurrentFolder.EndsWith("/" + folders[i])) { %> <li class="breadcrumb-item active"><%= folders[i] %></li> <% } else { %> <li class="breadcrumb-item"><a class="text-decoration-none" href="<%= RootFolderNav %>?folder=<%= "/" + string.Join("/", folders.Take(i + 1)) %>"><%= folders[i] %></a></li> <% } } } else { %> <li class="breadcrumb-item"><%= CurrentFolder %></li> <% } %> </ol> </nav> <% } %> </div> <% if (UseDataTables && UseDataTablesSearch) { %> <div class="col-12 col-md-3 col-xl-2"> <input type="search" placeholder="<%= TxtDatatableSearch %>" maxlength="50" class="form-control form-control-sm search-datatable"> </div> <% } %> </div> <% } %> <div class="row"> <div class="col"> <!-- the table with all the files --> <table class="table table-striped table-datatable <%= UseDataTables ? "opacity-0" : "" %>" id="vdwwd_datatable_<%= Regex.Replace(CurrentFolder, "[^a-zA-Z0-9]", "") %>"> <thead> <tr> <% if (UseDataTables) { %> <th class="d-none"></th> <% } %> <th class="w-75"><%= TxtColumnFileName %> </th> <th class="text-end"><%= TxtColumnDate %> </th> <th class="text-end"><%= TxtColumnType %> </th> <th class="text-end"><%= TxtColumnSize %> </th> </tr> </thead> <tbody> <!-- loop all the folders --> <% if (BrowseSubFolders) { if (!string.IsNullOrEmpty(CurrentFolder)) { %> <!-- add the up folder link if not root --> <% if (IsSubFolder) { %> <tr> <% if (UseDataTables) { %> <td class="d-none">0</td> <% } %> <td> <div class="float-start"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="me-3"> <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path> <line x1="9" y1="14" x2="15" y2="14"></line> </svg> </div> <div class="fw-bold"> <a href="<%= RootFolderNav %>?folder=<%= ParentFolder %>" class="text-decoration-none"> <%= TxtFolderUp %> </a> </div> </td> <td></td> <td></td> <td></td> </tr> <% } %> <!-- loop the folders --> <% } foreach (var Folder in AllFolders) { %> <tr> <% if (UseDataTables) { %> <td class="d-none">1</td> <% } %> <td> <div class="float-start"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="me-3"> <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path> </svg> </div> <div class="fw-bold"> <a href="<%= RootFolderNav %>?folder=<%= (IsSubFolder ? CurrentFolder + "/" : CurrentFolder) + Folder.Name.Replace(" ", "%20") %>" class="text-decoration-none"> <%= Folder.Name %> </a> </div> </td> <td></td> <td></td> <td></td> </tr> <% } } %> <!-- loop all the files --> <% foreach (var File in AllFiles) { %> <tr> <% if (UseDataTables) { %> <td class="d-none">2</td> <% } %> <td> <a target="_blank" class="text-decoration-none" href="<%: DownloadLinkPrefix + File.Name %>"> <div> <%= File.Name %> </div> </a> </td> <td class="text-end text-nowrap"> <%= File.CreationTime.ToShortDateString() %> </td> <td class="text-end text-nowrap"> <%= File.Extension.Replace(".", "").ToUpper() %> </td> <td class="text-end text-nowrap"> <span class="d-none"><%: File.Length.ToString().PadLeft(15, '0') %></span> <%= string.Format("{0:N1}", (decimal)File.Length / SizeDivider) %> </td> </tr> <% } %> <!-- if there are no files show error message --> <% if (!AllFiles.Any()) { %> <tr> <% if (UseDataTables) { %> <td class="d-none">1</td> <% } %> <td class="dataTables_empty"> <%= TxtDatatableEmpty %> </td> <td></td> <td></td> <td></td> </tr> <% } %> </tbody> <!-- show the footer --> <% if (ShowFooter) { %> <tfoot> <tr> <td colspan="5" class="fw-bold"> <%= string.Format(TxtFooter, AllFiles.Count(), (decimal)AllFiles.Sum(x => x.Length) / SizeDivider, ShowSizeInMb ? TxtSizeMb : TxtSizeKb) %> </td> </tr> </tfoot> <% } %> </table> </div> </div> </div> <div class="container"> <div class="row"> <div class="col text-center pt-4"> <a target="_blank" href="https://www.vanderwaal.eu"> <img src="https://www.vanderwaal.eu/images/vdwwd.png" alt="van der Waal Webdesign" title="van der Waal Webdesign" width="20%" /> </a> </div> </div> </div> <% if (UseDataTables) { %> <!-- if datatables are allowed --> <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script> <script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script> <link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet" /> <% if (UseDataTablesSearch) { %> <script src="https://cdn.jsdelivr.net/g/mark.js(jquery.mark.min.js)"></script> <script src="https://cdn.datatables.net/plug-ins/1.10.13/features/mark.js/datatables.mark.js"></script> <% } %> <style> .dataTables_filter { display: none; } table.dataTable td.dataTables_empty { text-align: left; padding: 20px; color: red; } mark { background: orange; color: black; padding: 0px 2px; } </style> <script> $(document).ready(function () { var $table = $('.table-datatable'); var $search = $table.closest('.container').find('.search-datatable'); //initialze the datatable var $datatable = $table.DataTable({ 'stateSave': true, 'stateDuration': -1, 'searching': <%= UseDataTablesSearch.ToString().ToLower() %>, 'paging': false, 'info': false, 'mark': { separateWordSearch: false }, 'orderFixed': [0, 'asc'], 'language': { 'emptyTable': '<%= TxtDatatableEmpty %>', 'search': '<%= TxtDatatableSearch %>:', 'zeroRecords': '<%= TxtDatatableNohits %>' }, }); //only show the datatable after initialization to hide the flickering of content due to creating or sorting contents $table.removeClass('opacity-0'); <% if (UseDataTablesSearch) { %> //search the datatable on keyup from an external input $search.on('keyup', function () { $datatable.search(this.value).draw(); }); //make the x button in the search input remove the search from the datatable $search.on('search', function () { if ($(this).val() === '') { $search.trigger('keyup'); } }); //if there is a search saved in the savestate of the datatable then fill the external input with that value $search.val($datatable.search()); <% } %> }); </script> <% } %> </body> </html>