Click here to Skip to main content
15,880,543 members
Articles / Web Development / ASP.NET
Tip/Trick

Exploring a Folder and its Subdirectories using ASP.NET MVC

Rate me:
Please Sign up or sign in to vote.
4.86/5 (11 votes)
7 Feb 2013CPOL2 min read 110.1K   4.7K   20   26
This article shows how you can easily make hyperlinks for exploring a folder on server and its subdirectories and downloading the files, using ASP.NET MVC.

Demo

Introduction

I had about 3000 PDF, ZIP and JPG files in too many folders on my server and wanted to simply make hyperlinks for exploring them on server in my site template and users can download the files in folders. This tip will show how you can easily make hyperlinks for exploring a folder on server and its subdirectories and downloading the files, using ASP.NET MVC.

Using the Code

This demo uses a default ASP.NET MVC 4 project.

New MVC project

We need to add Explorer Controller and its Index View, add ExplorerModel.cs, some edit in RouteConfig.cs and also add "Folder" that contain the files and folders for exploring and downloading.

Solution Explorer

Explorer Model

First of all, we need a model. So we add ExplorerModel.cs to Models. This model contains three classes. You could add every property that you want the classes to contain. In this demo, we made some simple models.
A class for DirModel that contains a directory information.

C#
public class DirModel
{
    public string DirName { get; set; }
    public DateTime DirAccessed { get; set; }
}

A class for FileModel that contains file information.

C#
public class FileModel
{
    public string FileName { get; set; }
    public string FileSizeText { get; set; }
    public DateTime FileAccessed { get; set; }
}

A class for ExplorerModel that contains directories and files list.

C#
public class ExplorerModel
{
    public List<DirModel> dirModelList;
    public List<FileModel> fileModelList;

    public ExplorerModel(List<DirModel> _dirModelList, List<FileModel> _fileModelList)
    {
        dirModelList = _dirModelList;
        fileModelList = _fileModelList;
    }
}

Explorer Controller

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using FolderExplorer.Models;
using System.IO;

namespace FolderExplorer.Controllers
{
    public class ExplorerController : Controller
    {
        //
        // GET: /Explorer/

        public ActionResult Index(string path)
        {
            string realPath;
            realPath = Server.MapPath("~/Folder/" + path);
            // or realPath = "FullPath of the folder on server" 

            if (System.IO.File.Exists(realPath))
            {
                //http://stackoverflow.com/questions/1176022/unknown-file-type-mime
                return base.File(realPath, "application/octet-stream");
            }
            else if (System.IO.Directory.Exists(realPath))
            {

                Uri url = Request.Url;
                //Every path needs to end with slash
                if (url.ToString().Last() != '/')
                {
                    Response.Redirect("/Explorer/" + path + "/");
                }

                List<FileModel> fileListModel = new List<FileModel>();

                List<DirModel> dirListModel = new List<DirModel>();

                IEnumerable<string> dirList = Directory.EnumerateDirectories(realPath);
                foreach (string dir in dirList)
                {
                    DirectoryInfo d = new DirectoryInfo(dir);

                    DirModel dirModel = new DirModel();

                    dirModel.DirName = Path.GetFileName(dir);
                    dirModel.DirAccessed = d.LastAccessTime;

                    dirListModel.Add(dirModel);
                }

                IEnumerable<string> fileList = Directory.EnumerateFiles(realPath);
                foreach (string file in fileList)
                {
                    FileInfo f = new FileInfo(file);

                    FileModel fileModel = new FileModel();

                    if (f.Extension.ToLower() != "php" && f.Extension.ToLower() != "aspx"
                        && f.Extension.ToLower() != "asp")
                    {
                        fileModel.FileName = Path.GetFileName(file);
                        fileModel.FileAccessed = f.LastAccessTime;
                        fileModel.FileSizeText = (f.Length < 1024) ? 
                                 f.Length.ToString() + " B" : f.Length / 1024 + " KB";

                        fileListModel.Add(fileModel);
                    }
                }

                ExplorerModel explorerModel = new ExplorerModel(dirListModel, fileListModel);

                return View(explorerModel);
            }
            else
            {
                return Content(path + " is not a valid file or directory.");
            }
        }
    }
}

As you can see, ExplorerController has only one action. Index action gets the path parameter.

C#
public ActionResult Index(string path)

How can we use path as UrlParameter?
If we browse "http://localhost:45114/Explorer/", we will see the files and directories in "Folder" and if we browse "http://localhost:45114/Explorer/Test%20Folder%201/Folder1/", we will see the files and directories in "Folder\Test Folder 1\Folder1". Because everything after "Explorer/" is our path and path contains some slashes and maybe spaces, so we can use URL: "Explorer/{*path}" in Explorer routes.MapRoute. So we must add the code below to RouteConfig.cs. See this for custom routes and MVC URLs with slash in parameter.

C#
routes.MapRoute(
    name: "Explorer",
    url: "Explorer/{*path}",
    defaults: new { controller = "Explorer",
                    action = "Index",
                    path = UrlParameter.Optional }
);

The following code will define the folder, that you want to use for exploring, you could use any method that you prefer to define this, like using Web.Config, Injection or ... It's not important. This code is just used for demo. See this for Server.MapPath.

C#
string realPath;
realPath  = Server.MapPath("~/Folder/" + path);
// or realPath = "FullPath of the folder on server"

Now we will check if the realPath is a file that exists. If it exists, we will send the contents of file as the response by using "return base.File(realPath, "application/octet-stream")". See this for more information about File. We will use "application/octet-stream" as contentType (See this).

C#
if (System.IO.File.Exists(realPath))
{
    return base.File(realPath, "application/octet-stream");
}

If realPath wasn't a file, then we check if it's a directory or not.

C#
else if (System.IO.Directory.Exists(realPath))
{
.
.
.
    return View(explorerModel);
}
else
{
    return Content(path + " is not a valid file or directory.");
}

For using browser ability to correctly browse the folders, every path needs to end with slash. The following codes do these:

C#
Uri url = Request.Url;

if (url.ToString().Last() != '/')
{
    Response.Redirect("/Explorer/" + path + "/");
}

Then we need to define the list that contains DirModels:

C#
List<DirModel> dirListModel = new List<DirModel>();
IEnumerable<string> dirList = Directory.EnumerateDirectories(realPath);
foreach (string dir in dirList)
{
    DirectoryInfo d = new DirectoryInfo(dir);

    DirModel dirModel = new DirModel();

    dirModel.DirName = Path.GetFileName(dir);
    dirModel.DirAccessed = d.LastAccessTime;

    dirListModel.Add(dirModel);
}

Also, we need to define the list that contains FileModels:

C#
List<FileModel> fileListModel = new List<FileModel>();
IEnumerable<string> fileList = Directory.EnumerateFiles(realPath);
foreach (string file in fileList)
{
    FileInfo f = new FileInfo(file);

    FileModel fileModel = new FileModel();

    //if file extension was php or aspx or asp we will skip them
    if (f.Extension.ToLower() != "php" && f.Extension.ToLower() != "aspx"
        && f.Extension.ToLower() != "asp")
    {
        fileModel.FileName = Path.GetFileName(file);
        fileModel.FileAccessed = f.LastAccessTime;
        fileModel.FileSizeText =
        (f.Length < 1024) ? f.Length.ToString() + " B" : f.Length / 1024 + " KB";

        fileListModel.Add(fileModel);
    }
}

Finally, we return explorerModel to Explorer Index View.

C#
ExplorerModel explorerModel = new ExplorerModel(dirListModel, fileListModel);

return View(explorerModel);

Explorer Index View

The description included in code:

HTML
@{
    ViewBag.Title = "Folder Explorer";
}
@{Uri uri = Request.Url;}

@*Show the current directory name using page URL. *@
<h2>@Server.UrlDecode(uri.Segments.Last())</h2>

@*If we were in root folder then don't show the up one level image. *@
@if (uri.AbsolutePath.ToLower() != "/explorer/")
{
    @*Making a URL to going up one level. *@
    <a title="Parent"
        href="@uri.AbsoluteUri.Remove(uri.AbsoluteUri.Length - uri.Segments.Last().Length)">
        <img src="http://www.codeproject.com/Content/up.png" 
         alt="Up" style="width: 20px; height: 20px; border: none" />
    </a>
}
<ul>
    @*Listing the directories *@
    @foreach (FolderExplorer.Models.DirModel dir in Model.dirModelList)
    {
        <li>
            <img src="http://www.codeproject.com/Content/folder.png" 
             alt="Folder Logo" align="top" style="width: 20px;
                height: 20px; border: none" />
            <a href="@dir.DirName/" title="@dir.DirName">@dir.DirName</a> 
            . . . . . . @dir.DirAccessed
        </li>
    }
    @*Listing the files *@
    @foreach (FolderExplorer.Models.FileModel file in Model.fileModelList)
    {
        <li><a href="@(uri.AbsolutePath + file.FileName)" 
        title="@file.FileName" target="_blank">
            @file.FileName</a>. . . . . . @file.FileSizeText
            . . . . . . @file.FileAccessed
        </li>
    }
</ul>

Related Tip

You can find the .NET Core version here.

Summary

This demo worked for me and it's serving the users. Hope it helps you too. Please don't forget to mark your votes, suggestions and feedback to improve the quality of this tip.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
“If you can't explain it simply, you don't understand it well enough.”
Albert Einstein

Comments and Discussions

 
Questionhow to read the content of the file Pin
Member 1422097225-Jun-19 23:33
Member 1422097225-Jun-19 23:33 
QuestionNeed Urgent Help Pin
Member 1157498424-Sep-18 2:54
Member 1157498424-Sep-18 2:54 
AnswerRe: Need Urgent Help Pin
Nikfazan8-Nov-18 13:41
professionalNikfazan8-Nov-18 13:41 
QuestionNice Work Pin
Mike Hankey9-Feb-17 23:24
mveMike Hankey9-Feb-17 23:24 
QuestionThanks! Pin
WADE POLK23-Dec-16 5:13
WADE POLK23-Dec-16 5:13 
QuestionHTTP ERROR 404 Pin
rnexus18-Feb-16 8:58
rnexus18-Feb-16 8:58 
AnswerRe: HTTP ERROR 404 Pin
Nikfazan21-Feb-16 6:05
professionalNikfazan21-Feb-16 6:05 
GeneralRe: HTTP ERROR 404 Pin
Ali Harahap13-Jul-17 2:22
Ali Harahap13-Jul-17 2:22 
AnswerRe: HTTP ERROR 404 Pin
Nikfazan17-Aug-17 12:39
professionalNikfazan17-Aug-17 12:39 
GeneralRe: HTTP ERROR 404 Pin
rnexus7-Nov-17 11:53
rnexus7-Nov-17 11:53 
GeneralRe: HTTP ERROR 404 Pin
Dung Pham9-Jan-18 12:13
Dung Pham9-Jan-18 12:13 
AnswerRe: HTTP ERROR 404 Pin
Nikfazan14-Jan-18 9:31
professionalNikfazan14-Jan-18 9:31 
GeneralRe: HTTP ERROR 404 Pin
naskigi24-Mar-20 1:09
naskigi24-Mar-20 1:09 
Questionhelp me please Pin
Member 1189368211-Oct-15 10:33
Member 1189368211-Oct-15 10:33 
AnswerRe: help me please Pin
Nikfazan24-Nov-15 1:04
professionalNikfazan24-Nov-15 1:04 
QuestionHow to add a checkbox for download capability? Pin
MLightsOut8-Apr-15 7:37
MLightsOut8-Apr-15 7:37 
AnswerRe: How to add a checkbox for download capability? Pin
Nikfazan8-Apr-15 9:35
professionalNikfazan8-Apr-15 9:35 
Generaldamet garm dada Pin
ehsan babaei29-Mar-15 1:43
ehsan babaei29-Mar-15 1:43 
QuestionGreat job. Pin
JoshYates198029-Aug-14 8:21
professionalJoshYates198029-Aug-14 8:21 
QuestionHi Nikfazan ,Help me please Pin
Member 101876624-Aug-13 15:42
professionalMember 101876624-Aug-13 15:42 
AnswerRe: Hi Nikfazan ,Help me please Pin
Nikfazan4-Aug-13 18:49
professionalNikfazan4-Aug-13 18:49 
GeneralRe: Hi Nikfazan ,Help me please Pin
Member 101876625-Aug-13 13:46
professionalMember 101876625-Aug-13 13:46 
GeneralRe: Hi Nikfazan ,Help me please Pin
Nikfazan6-Aug-13 9:24
professionalNikfazan6-Aug-13 9:24 
GeneralMy vote of 3 Pin
mag1314-Feb-13 23:18
mag1314-Feb-13 23:18 
GeneralRe: My vote of 3 Pin
Nikfazan15-Feb-13 2:29
professionalNikfazan15-Feb-13 2:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.