Navigation

>> Home
 
ASP.NET (13)
Security (5)
"Classic" ASP (2)
C# (1)
VB.NET (1)
ASP and Flash (1)
 
About Us
 
Chinese Content German Content

 

Directory Browsing the .NET Way

Written by: Christoph Wille
Translated by: Bernhard Spuida
First published: 8/4/2000

From the 'Good Old Times' of ASP programming, many should remember the FileSystemObject object. It allows access to the file system for reading, writing and directory browsing. However, the object model is anything but perfect and as for binary files, the end of the tether is reached before we even start - it just can't be done.

And there are some other functions and properties which I would have liked to have. It looks as if these wishes would be fulfilled by the .NET Framework classes in the System.IO namespace. File processing was never easier and above all never more powerful.

For this article I have picked one part of file processing: listing of files and directories. I have built a few nice scripts that can be later used in your own applications. Additional articles will deal with reading and writing files.

The use of the source code in this article requires the Microsoft .NET Framework SDK installed on a Webserver. I also presume that the reader is familiar to some degree with the C# programming language.

Enumerating Drives

The first thing we should find out is which drives actually are available for browsing on the computer (listdrives.aspx):

<% @Page Language="C#" %>
<% @Import Namespace="System.IO" %>
<%
string[] achDrives = Directory.GetLogicalDrives();
int nNumOfDrives = achDrives.Length;

Response.Write("<ul>");
for (int i=0; i < nNumOfDrives; i++)
{
 Response.Write("<li><a href=\"listdir.aspx?dir=");
 Response.Write(Server.UrlEncode(achDrives[i]));
 Response.Write("\">" + achDrives[i]);
 Response.Write("</a><br>");
}
Response.Write("</ul>");
%>

In the System.IO namespace (bound in with the @Import Namespace instruction) there is a class called Directory. This represents functionalities that can be used with directories and this class also contains the static (callable without object instance) method GetLogicalDrives. This method gives us an array of strings containing the drive letters.

Of course I didn't leave it at a simple listing of the drives obtained through GetLogicalDrives - I added a link to a further page which gives information about the contents of the root directory of the drive.

Listing Directories and Files

We are in a directory now. What is of interest for us there? For example the subdirectories and files as well as the properties of the directory itself (date of creation etc.). The following source code listing of the file listdir.aspx demonstrates how the required functionality might be implemented:

<% @Page Language="C#" %>
<% @Import Namespace="System.IO" %>
<%
string strDir2List = Request.QueryString.Get("dir");
DirectoryInfo thisOne = null;
try
{
 thisOne = new DirectoryInfo(strDir2List);
 // Reading the directory properties
 Response.Write("<p>Creation: " + 
 thisOne.CreationTime.ToString() + "</p>");
 DirectoryInfo[] subDirectories = thisOne.GetDirectories();
 Response.Write("<ul>");
 for (int i=0; i < subDirectories.Length; i++)
 {
  Response.Write("<li><a href=\"listdir.aspx?dir=");
  Response.Write(Server.UrlEncode(subDirectories[i].FullName));
  Response.Write("\">" + subDirectories[i].Name);
  Response.Write("</a><br>");
 }
 Response.Write("</ul>");
 
 FileInfo[] theFiles = thisOne.GetFiles();
 Response.Write("<ul>");
 for (int i=0; i < theFiles.Length; i++)
 {
  Response.Write("<li><a href=\"showfile.aspx?file=");
  Response.Write(Server.UrlEncode(theFiles[i].FullName));
  Response.Write("\">" + theFiles[i].Name);
  Response.Write("</a><br>");
 }
 Response.Write("</ul>");
}
catch (Exception e)
{
 Response.Write("Access not possible, error: <i>");
 Response.Write(e.ToString() + "</i>");
 Response.End();
}
%>

Reading the directories works with the GetDirectories method, which returns an array of DirectoryInfo objects to me, with which I can then build the desired functionality (e.g. like here for another link for the Drill-Down). The same applies to the GetFiles method, which returns an array of FileInfo objects. More on this in the next section.

For what, please, do I need exception handling? Well, it might be that I try to access something which I am not allowed to access and then I get one across my knuckles (this case might also be well known from Real Life...). Seriously: for example, the NTFS permissions for the current user might not be sufficient (listing forbidden).

Displaying File Information

Now we are at file level. Of course, a file has many properties and the following example showfile.aspx presents just a subset of them. A glance at the documentation reveals the remainder of what I have left out to shorten the script.

<% @Page Language="C#" %>
<% @Import Namespace="System.IO" %>
<html>
<head><title>File Info</title></head>
<body>
<%
string strFile2Show = Request.QueryString.Get("file");
FileInfo thisOne = new FileInfo(strFile2Show);
%>
<table>
<tr><td>Name:</td><td><%=thisOne.Name%></td></tr>
<tr><td>Path:</td><td><%=thisOne.FullName%></td></tr>
<tr><td>Directory:</td><td><%=thisOne.DirectoryName%></td></tr>
<tr>
  <td>Date created:</td>
  <td><%=thisOne.CreationTime.ToString()%></td>
</tr>
<tr>
  <td>Size:</td>
  <td><%=thisOne.Length.ToString()%> Bytes</td>
</tr>
<tr>
  <td>Last access:</td>
  <td><%=thisOne.LastAccessTime.ToString()%></td>
</tr>
<tr>
  <td>Last modified:</td>
  <td><%=thisOne.LastWriteTime.ToString()%></td>
</tr>
</table>

<%
StreamReader theReader = thisOne.OpenText();
char[] theBuffer = new char[255];
int nRead = theReader.ReadBlock(theBuffer, 0, 255);
Response.Write("<pre>");
Response.Write(Server.HtmlEncode(new String(theBuffer,0,nRead)));
Response.Write("</pre>");
%>

</body>
</html>

At the end of the script I undertook a quick detour to file reading to demonstrate how simple it is. First I open a StreamReader object, create a buffer, fill the buffer with the ReadBlock method and pass the HTML-encoded block over to the client. And presto, a tiny 'File Preview'!. Nothing earth shattering, but it already shows how simple working with the contents of files is.

Recursive Listing of Directories

At last, I have a program for creating a directory tree in mind. As the heading already indicates, the tree will be generated recursively - thus we need a function which can be called recursively. In the example recursivelisting.aspx it is called RecursiveDump:

<% @Page Language="C#" %>
<% @Import Namespace="System.IO" %>
<%
string strDir2List = Request.QueryString.Get("dir");
DirectoryInfo thisOne = new DirectoryInfo(strDir2List);

Response.Write("<pre>");
RecursiveDump(thisOne, 0);
Response.Write("</pre>");
%>

<script language="C#" runat="server">
void RecursiveDump(DirectoryInfo theDir, int nLevel)
{
  DirectoryInfo[] subDirectories = theDir.GetDirectories();
  for (int i=0; i < subDirectories.Length; i++)
  {
    Response.Write(new String(' ',nLevel));
    Response.Write(subDirectories[i].Name + "\r\n");
    RecursiveDump(subDirectories[i], nLevel+1);
  }
}
</script>

As usual I have made life easier for myself and just use blank spaces for generating the tree. To make that visible in HTML, we have to use a <PRE> Tag - otherwise the blanks will be gobbled up.

The function itself has two parameters: a DirectoryInfo object, and an integer variable which denotes the current level. For the current level, the subdirectories are read (with GetDirectories) and then displayed in a for loop. For each DirectoryInfo object the function RecursiveDump is called, and level is increased by one.

The result might look like this (Attention: listing an entire drive might take quite some time!):

Conclusion

In this article, I presented two objects out of the System.IO namespace: Directory and File. Though I used them 'only' for displaying simple directory and file information, these two objects are the base for file processing such as reading and writing. More on this in a future article.

Downloading the Code

Click here to start the download.

©2000-2004 AspHeute.com
All rights reserved. The content of these pages is copyrighted.
All content and images on this site are copyright. Reuse (even parts) needs our written consent.