Pulsa para probar la página dinámica ASPX:
ASP .NET tiene varias formas de aceder a los
archivos y subdirectorios contenidos en un directorio. En este ejercicio se
hace referencia a dos maneras diferentes de listar los archivos existentes en
una carpeta o directorio, ambas se basan en código relativamente sencillo,
comprensible por programadores de nivel básico / intermedio.
Usando colecciones y la interfaz
System.Collection.IEnumerator
Una colección (Collection) es un tipo especial de matriz o array
especialmente preparado para unas tareas determinadas. Los objetos Collection
se crean desde las clases e interfaces del espacio de nombres System.Collections.
Algunas interfaces útiles de Collections son:
En este ejercicio se usa la interfaz IEnumerator (que admite una
iteración simple a través de una colección) y el método GetEnumerator (que
devuelve un enumerador que puede iterar por una colección). IEnumerator es
la interfaz base de todos los enumeradores.
Los enumeradores sólo permiten la lectura de datos de la colección y no se
pueden utilizar para modificar la colección (acceden a las matrices en modo de
sólo
lectura
).
Inicialmente, el enumerador se coloca delante del primer elemento de la
colección y mediante sus métodos podemos movernos por la lista:
Alcanzado el final, el enumerador se coloca después del último elemento. Un enumerador no tiene acceso exclusivo a la colección, ésto ha de ser tenido en cuenta en cuanto a la seguridad de los procedimientos (no proporciona gran seguridad).
En el código de ejemplo se observa cómo se crea un array o lista para
contener los nombres de los archivos del directorio pasado en una variable de
cadena y también se crea un enumerador que itera a lo largo de los elementos de
la lista; se puede obtener fácilmente el número de archivos del directorio
contando el número de elementos de la lista (
i =
lista1.Length
).
El objeto Response permite interaccionar servidor con cliente, su método Write
envía resultados HTTP al navegador web cliente. Aquí lo utilizamos para ir
enviando código HTML que va formateando una tabla cuyas celdas se irán
rellenando con texto y resultados de la ejecución de código VB, aprovechando
para formatear el aspecto del documento HTML gracias a múltiples Response.Write:
Sub Listar1(ByVal sender As System.Object, ByVal e As System.EventArgs) Try Response.Write ("<h2 align=center style='font-family:verdana;'>Listar archivos de un directorio</h2>") 'array de cadenas para contener los nombres de los archivos del directorio Dim lista1() As String lista1 = System.IO.Directory.GetFiles(ruta) 'objeto IEnumerator que permitirá recorrer la lista de archivos Dim lista2 As System.Collections.IEnumerator 'lista2 se forma desde el método GetEnumerator de lista1 'GetEnumerator construye un objeto enumerador que contiene: ' - el número de versión de la colección ' - una referencia a los elementos de la colección lista2 = lista1.GetEnumerator 'i: entero para contener el número de archivos del directorio 'j: entero para contener la longitud de la cadena ruta i = lista1.Length j = ruta.Length 'crear la tabla en cuyas celdas aparece la información 'se usan estilos CSS para dar formato a las celdas Response.Write ("<table align=center border=0'>") Response.Write ("<tr style='font-family:verdana; font-size:10pt; font-weight:bold; text-align:center;background-color:black; color:white;'><td>") 'cabecera de la tabla con el nombre del directorio Response.Write ("<b>Directorio: " & ruta2 & "</b>") Response.Write ("</td></tr>") Response.Write ("<tr style='font-family:verdana; font-size:10pt; text-align:center;background-color:blue; color:white;'><td>") 'fila con el número de archivos del directorio Response.Write ("Número de archivos: <b>" & i & "</b>") Response.Write ("</td></tr>") 'se van leyendo los elementos de la colección hasta el final de la misma While lista2.MoveNext Response.Write ("<tr style='font-family:verdana; font-size:10pt; text-align:left;background-color:Gainsboro; color:black;'><td>") 'lista.Current devuelve el nombre largo de archivo (con ruta incluida) 'para dejar sólo el nombre corto de archivo (sin la ruta): ' - si la variable ruta termina en \ se quita de lista.Current la longitud de la variable '(ruta termina en \ si se forma con ServerMapPath (ej: ruta = Server.MapPath("/img")) ' - si la variable ruta NO termina en \ se quita de lista.Current la longitud de la variable más 1 carácter '(ruta NO termina en \ si se forma con la ruta como cadena sencilla (ej: ruta="C:\Windows") If ruta.EndsWith("\") Then Response.Write (CStr(lista2.Current).Remove(0, (j))) Else Response.Write (CStr(lista2.Current).Remove(0, (j + 1))) End If Response.Write ("</tr></td>") End While Response.Write ("</table>") Catch pollo As Exception Response.Write ("<p align=center style='font-family:verdana; font-size:10pt; color:red;'><b>" & _ pollo.Message & "</b></p>") Response.End () 'detiene la carga de la página End Try Response.End () 'detiene la carga de la página End Sub
Usando File, Directory, FileInfo y DirectoryInfo de
System.IO
El espacio de nombres System.IO contiene clases que
facilitan el trabajo con archivos y carpetas:
En este ejercicio se utilizan las clases FileInfo y DirectoryInfo junto a matrices para contener los nombres de las carpetas o archivos, para poder mostrar al usuario un listado de archivos contenidos en el directorio seleccionado y en los subdirectorios de primer nivel, de entre los que componen el sitio web del que forma parte esta aplicación. Es muy sencillo retocar el código para que muestre archivos de directorios locales del disco duro fuera de las carpetas que componen el servidor web pero para ello hay que tener permisos de acceso a esas carpetas, por lo que puede no funcionar sirviendo estas páginas desde Internet (el proveedor de los servicios tal vez no lo permita).
'listar los archivos de un directorio y del primer subnivel de directorios Sub Listar3(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim archivo, carpeta As String 'para el nombre de archivos y carpetas Dim sArchivos(), sCarpetas() As String 'array con los nombres de archivos y carpetas Dim carpetaInfo As DirectoryInfo 'objeto para extraer propiedades de las carpetas Dim archivoInfo As FileInfo 'objeto para extraer propiedades de los archivos Try 'el objeto Response permite interaccionar servidor con cliente, 'su método Write envía resultados HTTP al navegador web cliente. 'Aquí lo utilizamos para ir enviando código HTML que va formateando una tabla 'cuyas celdas se irán rellenando con texto y resultados de la ejecución de código VB Response.Write ("<h2 align=center style='font-family:verdana;'>Listar archivos de un directorio</h2>") 'array con los nombres de archivo en el directorio actual sArchivos = Directory.GetFiles(ruta) sCarpetas = Directory.GetDirectories(ruta) 'número de archivos en el directorio i = sArchivos.Length 'crear la tabla y la cabecera con títulos de columnas Response.Write ("<table align=center border=0 style='font-family:verdana; font-size:10pt;'>") Response.Write ("<tr style='background-color:black; color:white; font-weight:bold;'>") Response.Write ("<td>Nombre</td>") Response.Write ("<td align=right>Tamaño</td>") Response.Write ("<td align=center>Fecha</td>") Response.Write ("<td align=center>Hora</td></tr>") 'sección que lista los archivos que cuelgan directamente del directorio actual 'condiciones: listar sólo en carpetas con al menos 1 archivo If i > 0 Then Response.Write ("<tr><td colspan=4 align=center style='background-color:gray; color:white;'>") Response.Write ("<b>Directorio " & ruta2 & " [archivos: " & i & "]") End If Response.Write ("</td></tr>") 'Obtener lista de archivos contenidos en el directorio actual For Each archivo In sArchivos archivoInfo = New FileInfo(archivo) Response.Write ("<tr>") Response.Write ("<td bgcolor=Gainsboro>" & archivoInfo.Name & "</td>") Response.Write ("<td bgcolor=Gainsboro align=right>" & archivoInfo.Length.ToString("#,#") & " bytes</td>") Response.Write ("<td bgcolor=Gainsboro align=center>" & archivoInfo.CreationTime.ToShortDateString & "</td>") Response.Write ("<td bgcolor=Gainsboro align=center>" & archivoInfo.CreationTime.ToLongTimeString & "</td></tr>") Next 'Obtener lista de directorios del directorio actual For Each carpeta In sCarpetas 'For Each carpeta In Directory.GetDirectories(ruta) carpetaInfo = New DirectoryInfo(carpeta) 'array con nombres de archivos en cada directorio sArchivos = Directory.GetFiles(carpeta) 'número de carpetas en el directorio j = sArchivos.Length 'sección que lista las carpetas que cuelgan directamente del directorio 'condición: listar sólo en carpetas con al menos 1 archivo 'If j > 0 Then Response.Write ("<tr><td colspan=4 align=center style='background-color:gray; color:white;'>") 'condición: ocultar algunos directorios que no queremos que aparezcan en la lista If carpetaInfo.Name <> "_emi" Then If ruta2 = "/" Then Response.Write ("<b>Directorio: " & ruta2 & carpetaInfo.Name & " [archivos: " & j & "]") ElseIf ruta2.StartsWith("C:\") Then Response.Write ("<b>Directorio: " & ruta2 & "\" & carpetaInfo.Name & " [archivos: " & j & "]") Else Response.Write ("<b>Directorio: " & ruta2 & "/" & carpetaInfo.Name & " [archivos: " & j & "]") End If End If 'End If Response.Write ("</td></tr>") 'calcular el número total de archivos que hay en los directorios i += j 'obtener lista de archivos contenidos en los directorios de primer nivel 'sección que lista los archivos de esos directorios For Each archivo In Directory.GetFiles(carpeta) archivoInfo = New FileInfo(archivo) Response.Write ("<tr bgcolor=Gainsboro><td>/" & carpetaInfo.Name & archivoInfo.Name & "</td>") Response.Write ("<td bgcolor=Gainsboro align=right>" & archivoInfo.Length.ToString("#,#") & " bytes</td>") Response.Write ("<td bgcolor=Gainsboro>" & archivoInfo.CreationTime.ToShortDateString & "</td>") Response.Write ("<td bgcolor=Gainsboro>" & archivoInfo.CreationTime.ToLongTimeString & "</td></tr>") Next Next Catch pollo As Exception ''finalizar la tabla con el Nº total de archivos listados ''sólo si el TextBox contiene alguna ruta 'If ruta2 <> "" Then ' Response.Write ("<tr><td colspan=4 align=center style='background-color:blue; color:white;'>") ' Response.Write ("<b>Número total de archivos = " & i & "</b>") ' Response.Write ("</td></tr>") 'End If Response.Write ("</table>") Response.Write ("<p align=center style='font-family:verdana; font-size:10pt; color:red;'>" & _ "<b>ERROR: " & pollo.Message & "</b></p>") Response.End () End Try 'finalizar la tabla con el Nº total de archivos listados Response.Write ("<tr><td colspan=4 align=center style='background-color:blue; color:white;'>") Response.Write ("<b>Número total de archivos = " & i & "</b>") Response.Write ("</td></tr>") Response.Write ("</table>") Response.End () 'detiene la carga de la página End Sub
Código común a ambos métodos
La página aspx presenta al usuario un cuadro de texto en el que se introduce la ruta a una carpeta del servidor web (incluido el directorio raíz /) o a una carpeta del disco duro, teniendo en cuenta que, ejecutada desde Internet, esta aplicación intenta acceder a contenidos que, dependiendo de la configuración del servidor web, es posible que no sean accesibles por no tener permisos suficientes para ello; es recomendable descargar la aplicación a nuestro disco duro y probarla desde ahí.
Se necesitan variables (String para los nombres de archivos y carpetas y arrays para contener las listas de archivos y carpetas y poder contarlos):
Dim archivo, carpeta As String
'para
el nombre de archivos y carpetas
Dim sArchivos(), sCarpetas() As
String
'array con los
nombres de archivos y directorios
Dim a, b As Integer
'para llevar la cuenta del nº de
archivos
Se crea el título de la página web en tiempo de ejecución, al cargar la página:
Private Sub
Page_Load(ByVal sender As
System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Response.Write (
"<HEAD><TITLE>Listado
de archivos</TITLE></HEAD>"
)
End Sub
La propiedad text del cuadro de texto se pasa, en el código Visual Basic, a una variable String que ayuda a construir la ruta hacia el directorio usando Server.MapPath():
'ruta relativa al directorio cuyos archivos se van a listar Dim ruta2 As String 'asignación del texto del TextBox ruta2 = txt.Text 'cadena que almacena la ruta dentro del servidor web Dim ruta As String = Server.MapPath(ruta2)
Por último, se propone una manera diferente a la habitual para descargar el archivo comprimido zip:
'descargar el archivo zip con la aplicación completa Sub zip(ByVal sender As System.Object, ByVal e As System.EventArgs) Response.Redirect("archivos.zip", True) End Sub