
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.

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.

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
{
public ActionResult Index(string path)
{
string realPath;
realPath = Server.MapPath("~/Folder/" + path);
if (System.IO.File.Exists(realPath))
{
return base.File(realPath, "application/octet-stream");
}
else if (System.IO.Directory.Exists(realPath))
{
Uri url = Request.Url;
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);
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 (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.