Recursive File List Control v2 (ASP.NET)
Much like the original Recursive File List Control, this user control lists files and folders within a virtual web folder. Improvements include - excludes directories ending in '_file' (i.e. those created by Internet Explorer when you download a web page), excludes files beginning with '~$' (i.e. temporary documents generated by Microsoft Office applications), multiple instances can be placed on a web page, postback does not end up causing duplication of list and it takes into account other querystring parameters that may be passed on to the page.
Control (filelist.ascx)
<%@ Control Language="C#" src="filelist.ascx.cs" Inherits="WebDeveloperBlog.RecursiveFileList" %>
Code behind (filelist.ascx.cs)
using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebDeveloperBlog
{
public class RecursiveFileList : UserControl
{
protected HyperLink lnkReset;
protected Literal FileList;
/// <summary>
/// The virtual folder is the initial folder to start with, default root of application, but can be overridden by calling page
/// </summary>
public string VirtualFolder
{
get
{
if (ViewState["virtualFolder"]==null)
{
ViewState["virtualFolder"] = "~/";
}
return ViewState["virtualFolder"].ToString();
}
set
{
ViewState["virtualFolder"] = value;
}
}
/// <summary>
/// List of file types to show. Set up in the Control_Load function
/// </summary>
private ArrayList fileTypes = new ArrayList();
/// <summary>
/// For internal use only
/// </summary>
private ArrayList folders;
/// <summary>
/// List of folders to be show files/folders in
/// </summary>
protected ArrayList Folders
{
get
{
if (folders == null)
{
if (UrlPathInfo != null)
{
folders = new ArrayList(UrlPathInfo.Split(';'));
}
else
{
folders = new ArrayList();
}
}
return folders;
}
set
{
folders = value;
}
}
/// <summary>
/// The path to the aspx page calling this control
/// </summary>
private string UrlPath
{
get
{
return HttpContext.Current.Request.Path;
}
}
/// <summary>
/// The folders that are to be filtered. Used getting the folders from the Folders array list
/// </summary>
private string UrlPathInfo
{
get
{
return HttpContext.Current.Request.QueryString[FilterFolderParameter];
}
}
/// <summary>
/// The query parameter to use when checking which folders to display the folder/file contents of
/// </summary>
private string FilterFolderParameter
{
get
{
return this.ClientID.ToString() + "folders";
}
}
/// <summary>
/// Builds a list of folders from the Folders array list using ; as the deliminator
/// </summary>
private string BuildFolderList
{
get
{
string strList = string.Empty;
for(int i=0; i<Folders.Count; i++)
{
strList += HttpContext.Current.Server.UrlEncode(Folders[i].ToString()) + ";";
}
if (strList != string.Empty)
{
strList = strList.Substring(0, strList.LastIndexOf(';'));
}
return strList;
}
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Control_Load);
}
#endregion
private void Control_Load(object sender, EventArgs e)
{
// add file types
fileTypes.Add("doc");
fileTypes.Add("rtf");
fileTypes.Add("xls");
fileTypes.Add("pdf");
// add reset list link if not already added
if (lnkReset == null)
{
lnkReset = new HyperLink();
lnkReset.Text = "Reset list '" + VirtualFolder + "'";
this.Controls.Add(lnkReset);
}
// set result link to path of current page
string resetUrl = UrlPath;
NameValueCollection q = new NameValueCollection(HttpContext.Current.Request.QueryString);
q.Remove(FilterFolderParameter);
for (int i = 0; i <= q.Count - 1; i++)
{
if (i != 0)
{
resetUrl += "&";
}
else
{
resetUrl += "?";
}
resetUrl += q.GetKey(i) + "=" + q.Get(i);
}
lnkReset.NavigateUrl = resetUrl;
// add file list Literal control if not on page
if (FileList == null)
{
FileList = new Literal();
this.Controls.Add(FileList);
}
// recurse folder starting with the supplied virtual folder
if (!Page.IsPostBack)
{
RecurseFolders(VirtualFolder);
}
}
/// <summary>
/// Check if in Folders array list
/// </summary>
private bool InFolders(string s)
{
for(int i=0; i<Folders.Count; i++)
{
if(Folders[i].ToString() == s)
{
return true;
}
}
return false;
}
/// <summary>
/// Check if file is one that is allowed
/// </summary>
private bool AllowedFileType(string fileExt)
{
for(int i=0; i<fileTypes.Count; i++)
{
if(fileTypes[i].ToString() == fileExt.ToLower())
{
return true;
}
}
return false;
}
/// <summary>
/// Recurse folders in path, excluding those that aren't in the Folders array list
/// </summary>
private void RecurseFolders(string path)
{
// Open the list
FileList.Text += "<ul>";
string mappedRoot = HttpContext.Current.Server.MapPath(path);
HttpContext.Current.Trace.Write("WebDeveloperBlog.RecursiveFileList", "Folder: " + mappedRoot);
string[] folders = null;
try
{
folders = Directory.GetDirectories(mappedRoot);
// Iterate through each folder
foreach (string folder in folders)
{
// ignore folders ending in _files (these are folders used when saving web pages from Internet Explorer)
if (folder.Substring(folder.Length - 6) == "_files")
{
continue;
}
string virtfolder = folder.Replace(mappedRoot, string.Empty);
string subFolder = path + virtfolder + "/";
string[] subfolders = Directory.GetDirectories(folder);
string[] files = Directory.GetFiles(folder);
string whichfolders = string.Empty;
HttpContext.Current.Trace.Write("WebDeveloperBlog.RecursiveFileList", folder + "\n Sub folder count: " + subfolders.Length + "\n File count: " + files.Length);
if (InFolders(subFolder))
{
Folders.Remove(subFolder);
whichfolders = BuildFolderList;
Folders.Add(subFolder);
}
else
{
Folders.Add(subFolder);
whichfolders = BuildFolderList;
Folders.Remove(subFolder);
}
NameValueCollection q = new NameValueCollection(HttpContext.Current.Request.QueryString);
q[FilterFolderParameter] = whichfolders;
if (q[FilterFolderParameter] == string.Empty)
{
q.Remove(FilterFolderParameter);
}
FileList.Text += "<li><a href=\"" + UrlPath;
for (int i = 0; i <= q.Count - 1; i++)
{
if (i != 0)
{
FileList.Text += "&";
}
else
{
FileList.Text += "?";
}
FileList.Text += q.GetKey(i) + "=" + q.Get(i);
}
FileList.Text += "\">" + HttpContext.Current.Server.HtmlEncode(virtfolder) + "</a>";
if (InFolders(subFolder))
{
// recurse sub folder
FileList.Text += Environment.NewLine;
RecurseFolders(subFolder);
}
FileList.Text += "</li>" + Environment.NewLine;
}
}
catch (System.Exception ex)
{
HttpContext.Current.Trace.Warn("WebDeveloperBlog.RecursiveFileList", ex.Source, ex);
}
try
{
string[] files = Directory.GetFiles(mappedRoot);
// Iterate through the files in this folder
if(files.Length == 0)
{
if (folders.Length == 0)
{
FileList.Text += "<li>No files</li>" + Environment.NewLine;
}
}
else
{
foreach (string file in files)
{
string fileName = file.Replace(mappedRoot, string.Empty);
// ignore files beginning with ~$ (these are files generated by Microsoft Office applications)
if (fileName.Substring(0,2) == "~$")
{
continue;
}
if (!AllowedFileType(GetExt(fileName))) continue;
// link to file
FileList.Text += "<li> File: " + "<a href=\"" + path + fileName + "\">" + HttpContext.Current.Server.HtmlEncode(RemoveExt(fileName)) + "</a></li>";
// Put the fileName in the textbox
FileList.Text += Environment.NewLine;
}
}
}
catch (System.Exception ex)
{
HttpContext.Current.Trace.Warn("WebDeveloperBlog.RecursiveFileList", ex.Source, ex);
}
// Close the list
FileList.Text += "</ul>" + Environment.NewLine;
}
/// <summary>
/// Remove file extension from the supplied file name
/// </summary>
private string RemoveExt(string fileName)
{
return fileName.Substring(0,fileName.LastIndexOf('.'));
}
/// <summary>
/// Get the extension from the supplied file name
/// </summary>
private string GetExt(string fileName)
{
int dot = fileName.LastIndexOf('.') + 1;
return fileName.Substring(dot, fileName.Length - dot);
}
}
}
Sample page (filelist.aspx)
<%@ Page Language="C#" Trace="False" ContentType="text/html" ResponseEncoding="iso-8859-1" %> <%@ Register TagPrefix="Files" TagName="List" Src="filelist.ascx" %> <html> <head> <title>File listing</title> </head> <body> <form runat="server"> <Files:List runat="server" VirtualFolder="/virtualdir/" /> <Files:List runat="server" VirtualFolder="/virtualdir2/" /> </form> </body> </html>
Tags: Web Developer Blog, ASP.NET, CSharp
Comments