Directory Browsing a la .NET
Geschrieben von: Christoph Wille Aus den "guten alten Zeiten" des ASP Programmierens dürfte sehr vielen das FileSystemObject Objekt in Erinnerung sein. Es erlaubt Zugriff auf das Dateisystem für Lesen, Schreiben und Directory Browsing. Allerdings ist Objektmodell alles andere als optimal, und bei binären Dateien ist das Ende der Fahnenstange erreicht, bevor man am Ziel ist - es geht schlicht und ergreifend nicht. Auch sonst gibt es einige Funktionen und Eigenschaften, die ich sehr gerne gehabt hätte. Es scheint so, als würden diese Wünsche mit den .NET Framework Klassen im System.IO Namespace in Erfüllung gehen. Die Dateiverarbeitung war nie einfacher, und vor allem nie leistungsfähiger. Für diesen Artikel habe ich einen Teil der Dateiverarbeitung herausgepickt: das Auflisten von Dateien und Ordnern. Ich habe einige nette Scripts gebastelt, die man später in eigenen Applikationen einsetzen kann. Weitere Artikel werden sich mit dem Lesen und Schreiben von Dateien befassen. Voraussetzung um den Sourcecode dieses Artikels verwenden zu können ist eine Installation des Microsoft .NET Framework SDK's auf einem Webserver. Weiters setze ich voraus, daß der Leser die Programmiersprache C# zu einem gewissen Grad beherrscht - es finden sich etliche Artikel auf diesem Server, um das notwendige Wissen zu erlernen. Laufwerke aufzählenDas Erste, was wir herausfinden sollten ist, welche Laufwerke eigentlich so am Rechner für uns zum Herumstöbern verfügbar sind (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>"); %> Im System.IO Namespace (mit der @Import Namespace Anweisung eingebunden) gibt es eine Klasse namens Directory. Dieses repräsentiert Funktionalitäten die man mit einem Verzeichnis brauchen kann, und die Klasse enthält auch die statische (ohne Objektinstanz aufrufbare) Methode GetLogicalDrives. Diese liefert uns ein Array von Strings, die die Laufwerksbuchstaben enthalten. Natürlich habe ich es nicht bei einer einfachen Auflistung der über GetLogicalDrives erhaltenen Laufwerke belassen - ich habe gleich einen Link auf eine weiterführende Seite eingebaut, die dann Aufschluß über den Inhalt des Root-Verzeichnisses des Laufwerks gibt. Verzeichnisse und Dateien auflistenJetzt sind wir in einem Verzeichnis. Was interessiert uns dort? Zum Beispiel die Unterverzeichnisse und Dateien, als auch Eigenschaften des Verzeichnisses selbst (Erstellungsdatum, etc). Das folgende Sourcodelisting der Datei listdir.aspx zeigt, wie man die geforderte Funktionalität implementieren könnte: <% @Page Language="C#" %> <% @Import Namespace="System.IO" %> <% string strDir2List = Request.QueryString.Get("dir"); DirectoryInfo thisOne = null; try { thisOne = new DirectoryInfo(strDir2List); // Auslesen der Eigenschaften der Verzeichnisses Response.Write("<p>Erzeugung: " + 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("Zugriff nicht möglich, Fehler: <i>"); Response.Write(e.ToString() + "</i>"); Response.End(); } %> Das Auslesen der Verzeichnisse funktioniert mittels der GetDirectories Methode, die mir ein Array von DirectoryInfo Objekten liefert, mit denen ich dann meine gewünschte Funktionalität aufbauen kann (zB wie hier ein weiterer Link für den Drill-Down). Gleiches gilt für die GetFiles Methode, die ein Array von FileInfo Objekten liefert. Mehr zu diesem in der nächsten Sektion. Wozu brauche ich bitte schön das Exception Handling? Nun, es könnte ja sein, daß ich auf etwas zugreife, wo ich nicht hingreifen darf, und dann bekommt man eine auf die Finger (dieser Fall dürfte auch dem Real-Life bekannt sein...). Im Ernst: es könnten zum Beispiel die NTFS Rechte für den aktuellen Benutzer nicht ausreichend sein (Listen verboten). Dateiinformationen ausgebenJetzt sind wir auf der Dateiebene. Natürlich hat eine Datei eine Menge von Eigenschaften, und das folgende Beispiel showfile.aspx präsentiert nur eine Untermenge. Ein Blick in die Dokumentation enthüllt den Rest dessen, was ich zur Kürzung des Scripts ausgelassen habe. <% @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>Pfad:</td><td><%=thisOne.FullName%></td></tr> <tr><td>Verzeichnis:</td><td><%=thisOne.DirectoryName%></td></tr> <tr> <td>Erstellung:</td> <td><%=thisOne.CreationTime.ToString()%></td> </tr> <tr> <td>Länge:</td> <td><%=thisOne.Length.ToString()%> Bytes</td> </tr> <tr> <td>Letzter Zugriff:</td> <td><%=thisOne.LastAccessTime.ToString()%></td> </tr> <tr> <td>Letzte Modifikation:</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> Am Ende des Scripts habe ich einen kurzen Ausflug in Richtung Dateiauslesen unternommen, um zu demonstrieren, wie einfach das ist. Zuerst öffne ich ein StreamReader Objekt, lege einen Puffer an, fülle den Puffer mit der ReadBlock Methode und gebe den eingelesenen Block dann HTML-encoded mit an den Client aus. Und schon hat man eine kleine "Dateivorschau". Nicht gerade weltbewegend, aber es demonstriert bereits, wie einfach auch das Arbeiten mit den Inhalten von Dateien ist. Rekursives Auflisten eines VerzeichnissesZu guter Letzt habe ich noch ein kleines Programm zum Erzeugen eines Verzeichnisbaums in Petto. Wie die Überschrift schon verrät, wird der Baum rekursiv erzeugt - man braucht also eine Funktion, die rekursiv aufgerufen werden kann. Im Beispiel recursivelisting.aspx heißt diese 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> Wie immer habe ich es mir besonders einfach gemacht, und verwende einfach Leerzeichen um den Baum zu generieren. Damit man's in HTML auch sieht, muß man daher ein <PRE> Tag verwenden - sonst werden die Leerzeichen geschluckt. Die Funktion selbst hat 2 Parameter: ein DirectoryInfo Objekt, und eine Integervariable, die die aktuelle Ebene bezeichnet. Es werden für die aktuelle Ebene die Unterverzeichnisse ausgelesen (mit GetDirectories), und dann mit einer for Schleife ausgegeben. Für jedes DirectoryInfo Objekt wird die Funktion RecursiveDump aufgerufen, und die Ebene um 1 erhöht. Das Ergebnis kann dann so aussehen (Achtung: wenn man ein ganzes Laufwerk aufbauen läßt, so kann dies schon einige Zeit in Anspruch nehmen!): Schlußbemerkung:In diesem Artikel habe ich drei Objekte aus dem System.IO Namespace präsentiert: Directory, DirectoryInfo und FileInfo. Obwohl ich sie "nur" zum Ausgeben einfacher Verzeichnis- und Dateiinformationen verwendet habe, sind diese Objekte die Basis zur Dateiverarbeitung wie Lesen und Schreiben. Dazu aber mehr in einem späteren Artikel. Download des CodesKlicken Sie hier, um den Download zu starten. Verwandte Artikel
Dateien lesen in ASP.NET Links zu anderen Sites
Die aspDEdotnet Diskussionsliste Wenn Sie jetzt Fragen haben...Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten. Eine weitere sehr hilfreiche Resource ist das deutsche ASP.NET Wiki, das als zentrale Anlaufstelle für Tips, Tricks, Know How und alles Nützliche was man in seinem Alltag als (ASP).NET-Entwickler so braucht und entdeckt gedacht ist. Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.
Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.
©2000-2006 AspHeute.com |