Click here to Skip to main content
Click here to Skip to main content

Exploring a folder and its subdirectories using ASP.NET MVC

, 7 Feb 2013
Rate this:
Please Sign up or sign in to vote.
This article shows how you can easily making 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 making 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 making 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 explore and download.

Solution Explorer

Explorer Model

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

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

A class for FileModel that contains a file info.

    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.

    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

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 get the path parameter.

    public ActionResult Index(string path)

How we can 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

            routes.MapRoute(
                name: "Explorer",
                url: "Explorer/{*path}",
                defaults: new { controller = "Explorer",
                                action = "Index",
                                path = UrlParameter.Optional }
            );
Following code will define the folder, that you want use it for exploring, you could use any method that you prefere to defining this, like using Web.Config, Injection or ... . It's not important. This code just used for demo. See this for Server.MapPath
            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 exist. If it exist, we will send the contents of file as the response by using "return base.File(realPath, "application/octet-stream")" . See this for more info about File. We will use "application/octet-stream" as contentType ( See this).

            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.

            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 browsing the folders, Every path needs to end with slash. The following codes do these.

                Uri url = Request.Url;

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

Then we need to define the list that contains DirModels :

                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 :

                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

                ExplorerModel explorerModel = new ExplorerModel(dirListModel, fileListModel);

                return View(explorerModel);

Explorer Index View

The description included in code:

@{
    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>

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)

About the Author

Nikfazan
Software Developer (Senior)
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
نیک فزان
 
“If you can't explain it simply, you don't understand it well enough.”
Albert Einstein

Comments and Discussions

 
QuestionHi Nikfazan ,Help me please PinmemberMember 101876624-Aug-13 15:42 
AnswerRe: Hi Nikfazan ,Help me please PinprofessionalNikfazan4-Aug-13 18:49 
GeneralRe: Hi Nikfazan ,Help me please PinmemberMember 101876625-Aug-13 13:46 
GeneralRe: Hi Nikfazan ,Help me please PinprofessionalNikfazan6-Aug-13 9:24 
GeneralMy vote of 3 PinmemberLautas14-Feb-13 23:18 
GeneralRe: My vote of 3 PinmemberNikfazan15-Feb-13 2:29 
GeneralMy vote of 5 PinmemberS-Hasani10-Feb-13 20:17 

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

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

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 7 Feb 2013
Article Copyright 2013 by Nikfazan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid