Trabajar con archivos en un sitio de ASP.NET Web Pages (Razor)
por Tom FitzMacken
En este artículo se explica cómo leer, escribir, anexar, eliminar y cargar archivos en un sitio de ASP.NET Web Pages (Razor).
Nota:
Si desea cargar imágenes y manipularlas (por ejemplo, voltear o cambiar su tamaño), vea Trabajar con imágenes en un sitio de ASP.NET Web Pages.
Aprenderá lo siguiente:
- Cómo crear un archivo de texto y escribir datos en él.
- Cómo anexar datos a un archivo existente.
- Cómo leer un archivo y mostrarlo desde él.
- Cómo eliminar archivos de un sitio web.
- Cómo permitir que los usuarios carguen un archivo o varios archivos.
Las características de programación ASP.NET presentadas en el artículo son:
- Objeto
File
, que proporciona una manera de administrar archivos.- El asistente
FileUpload
.- El objeto
Path
, que proporciona métodos que permiten manipular la ruta de acceso y los nombres de archivo.Versiones de software usadas en el tutorial
- ASP.NET Web Pages (Razor) 2
- WebMatrix 2
Este tutorial también funciona con WebMatrix 3.
Crear un archivo de texto y escribir datos en él
Además de usar una base de datos en su sitio web, puede trabajar con archivos. Por ejemplo, puede usar archivos de texto como una manera sencilla de almacenar datos para el sitio. (A veces, un archivo de texto que se usa para almacenar datos se denomina archivo plano.) Los archivos de texto pueden tener diferentes formatos, como .txt, .xmlo .csv (valores delimitados por comas).
Si desea almacenar datos en un archivo de texto, puede usar el método File.WriteAllText
para especificar el archivo que se va a crear y los datos que se van a escribir en él. En este procedimiento, creará una página que contiene un formulario simple con tres elementos input
(nombre, apellido y dirección de correo electrónico) y un botón Enviar. Cuando el usuario envíe el formulario, almacenará la entrada del usuario en un archivo de texto.
Cree una carpeta denominada App_Data, si aún no existe.
En la raíz de su sitio web, cree un nuevo archivo denominado UserData.cshtml.
Reemplace el contenido existente por lo siguiente:
@{ var result = ""; if (IsPost) { var firstName = Request["FirstName"]; var lastName = Request["LastName"]; var email = Request["Email"]; var userData = firstName + "," + lastName + "," + email + Environment.NewLine; var dataFile = Server.MapPath("~/App_Data/data.txt"); File.WriteAllText(@dataFile, userData); result = "Information saved."; } } <!DOCTYPE html> <html> <head> <title>Write Data to a File</title> </head> <body> <form id="form1" method="post"> <div> <table> <tr> <td>First Name:</td> <td><input id="FirstName" name="FirstName" type="text" /></td> </tr> <tr> <td>Last Name:</td> <td><input id="LastName" name="LastName" type="text" /></td> </tr> <tr> <td>Email:</td> <td><input id="Email" name="Email" type="text" /></td> </tr> <tr> <td></td> <td><input type="submit" value="Submit"/></td> </tr> </table> </div> <div> @if(result != ""){ <p>Result: @result</p> } </div> </form> </body> </html>
El marcado HTML crea el formulario con los tres cuadros de texto. En el código, se usa la propiedad
IsPost
para determinar si la página se ha enviado antes de iniciar el procesamiento.La primera tarea consiste en obtener la entrada del usuario y asignarla a variables. A continuación, el código concatena los valores de las variables independientes en una cadena delimitada por comas, que luego se almacena en una variable diferente. Observe que el separador de comas es una cadena contenida entre comillas (","), porque literalmente va a insertar una coma en la cadena grande que está creando. Al final de los datos que concatene juntos, agregue
Environment.NewLine
. Esto agrega un salto de línea (un carácter de nueva línea). Lo que va a crear con toda esta concatenación es una cadena similar a la siguiente:David,Jones,davidj@contoso.com
(Con un salto de línea invisible al final.)
A continuación, cree una variable (
dataFile
) que contenga la ubicación y el nombre del archivo en el que almacenar los datos. La configuración de la ubicación requiere un control especial. En los sitios web, se recomienda hacer referencia al código a rutas de acceso absolutas, como C:\Folder\File.txt para archivos en el servidor web. Si se mueve un sitio web, una ruta de acceso absoluta será incorrecta. Además, para un sitio hospedado (en lugar de en su propio equipo), normalmente no sabe cuál es la ruta de acceso correcta al escribir el código.Pero a veces (como ahora, para escribir un archivo), necesita una ruta de acceso completa. La solución consiste en usar el
MapPath
método del objetoServer
. Esto devuelve la ruta de acceso completa a su sitio web. Para obtener la ruta de acceso de la raíz del sitio web, use el operador~
(para volver apresar la raíz virtual del sitio) paraMapPath
. (También puede pasarle un nombre de subcarpeta, como ~/App_Data/, para obtener la ruta de acceso de esa subcarpeta.) A continuación, puede concatenar información adicional sobre cualquier valor devuelto por el método para crear una ruta de acceso completa. En este ejemplo, agregará un nombre de archivo. (Puede obtener más información sobre cómo trabajar con rutas de acceso de archivos y carpetas en Introducción a la programación de ASP.NET Web Pages mediante la sintaxis de Razor.)El archivo se guarda en la carpeta App_Data. Esta carpeta es una carpeta especial en ASP.NET que se usa para almacenar archivos de datos, como se describe en Introducción al trabajo con una base de datos en ASP.NET Web Pages Sitios.
El
WriteAllText
método delFile
objeto escribe los datos en el archivo. Este método toma dos parámetros: el nombre (con ruta de acceso) del archivo en el que se va a escribir y los datos reales que se van a escribir. Observe que el nombre del primer parámetro tiene un carácter@
como prefijo. Esto indica ASP.NET que se proporciona un literal de cadena textual y que los caracteres como "/" no deben interpretarse de maneras especiales. (Para obtener más información, vea Introducción a la programación web ASP.NET usando la sintaxis Razor.)Nota:
Para que el código guarde archivos en la carpeta App_Data, la aplicación necesita permisos de lectura y escritura para esa carpeta. En el equipo de desarrollo, esto no suele ser un problema. Sin embargo, al publicar el sitio en el servidor web de un proveedor de hospedaje, es posible que tenga que establecer explícitamente esos permisos. Si ejecuta este código en el servidor de un proveedor de hospedaje y recibe errores, consulte con el proveedor de hospedaje para averiguar cómo establecer esos permisos.
Ejecute la página en un explorador.
Escriba los valores en los campos y, a continuación, haga clic en Enviar.
Cierre el explorador.
Vuelva al proyecto y actualice la vista.
Abra el archivo data.txt. Los datos que envió en el formulario están en el archivo.
Cierre el archivo data.txt.
Anexar datos a un archivo existente
En el ejemplo anterior, usó WriteAllText
para crear un archivo de texto que tiene solo un fragmento de datos. Si llama al método de nuevo y lo pasa con el mismo nombre de archivo, el archivo existente se sobrescribe por completo. Sin embargo, después de crear un archivo, a menudo desea agregar nuevos datos al final del archivo. Puede hacerlo mediante el método AppendAllText
del objeto File
.
En el sitio web, realice una copia del archivoUserData.cshtml y asigne un nombre al UserDataMultiple.cshtml.
Reemplace el bloque de código antes de la etiqueta de apertura
<!DOCTYPE html>
por el siguiente bloque de código:@{ var result = ""; if (IsPost) { var firstName = Request["FirstName"]; var lastName = Request["LastName"]; var email = Request["Email"]; var userData = firstName + "," + lastName + "," + email + Environment.NewLine; var dataFile = Server.MapPath("~/App_Data/data.txt"); File.AppendAllText (@dataFile, userData); result = "Information saved."; } }
Este código tiene un cambio en él del ejemplo anterior. En lugar de usar
WriteAllText
, usathe AppendAllText
método. Los métodos son similares, excepto queAppendAllText
agrega los datos al final del archivo. Al igual que conWriteAllText
,AppendAllText
crea el archivo si aún no existe.Ejecute la página en un explorador.
Escriba los valores de los campos y haga clic en Enviar.
Agregue más datos y vuelva a enviar el formulario.
Vuelva al proyecto, haga clic con el botón derecho en la carpeta del proyecto y, a continuación, haga clic en Actualizar.
Abra el archivo data.txt. Ahora contiene los nuevos datos que acaba de escribir.
Leer y mostrar datos de un archivo
Incluso si no necesita escribir datos en un archivo de texto, es probable que a veces necesite leer datos de uno. Para ello, puede usar de nuevo el objeto File
. Puede usar el objeto File
para leer cada línea individualmente (separados por saltos de línea) o para leer un elemento individual independientemente de cómo estén separados.
Este procedimiento muestra cómo leer y mostrar los datos que creó en el ejemplo anterior.
En la raíz de su sitio web, cree un nuevo archivo denominado DisplayData.cshtml.
Reemplace el contenido existente por lo siguiente:
@{ var result = ""; Array userData = null; char[] delimiterChar = {','}; var dataFile = Server.MapPath("~/App_Data/data.txt"); if (File.Exists(dataFile)) { userData = File.ReadAllLines(dataFile); if (userData == null) { // Empty file. result = "The file is empty."; } } else { // File does not exist. result = "The file does not exist."; } } <!DOCTYPE html> <html> <head> <title>Reading Data from a File</title> </head> <body> <div> <h1>Reading Data from a File</h1> @result @if (result == "") { <ol> @foreach (string dataLine in userData) { <li> User <ul> @foreach (string dataItem in dataLine.Split(delimiterChar)) { <li>@dataItem</li > } </ul> </li> } </ol> } </div> </body> </html>
El código comienza leyendo el archivo que creó en el ejemplo anterior en una variable denominada
userData
, con esta llamada de método:File.ReadAllLines(dataFile)
El código para hacerlo está dentro de una instrucción
if
. Cuando quiera leer un archivo, es recomendable usar el métodoFile.Exists
para determinar primero si el archivo está disponible. El código también comprueba si el archivo está vacío.El cuerpo de la página contiene dos
foreach
bucles, uno anidado dentro del otro. El bucle externoforeach
obtiene una línea a la vez del archivo de datos. En este caso, las líneas se definen mediante saltos de línea en el archivo, es decir, cada elemento de datos está en su propia línea. El bucle externo crea un nuevo elemento (<li>
elemento) dentro de una lista ordenada (<ol>
elemento).El bucle interno divide cada línea de datos en elementos (campos) mediante una coma como delimitador. (Según el ejemplo anterior, esto significa que cada línea contiene tres campos, el nombre, el apellido y la dirección de correo electrónico, cada uno separado por una coma.) El bucle interno también crea una lista
<ul>
y muestra un elemento de lista para cada campo de la línea de datos.El código muestra cómo usar dos tipos de datos, una matriz y el tipo de datos
char
. La matriz es necesaria porque el métodoFile.ReadAllLines
devuelve datos como una matriz. El tipo de datoschar
es necesario porque el métodoSplit
devuelve unarray
en el que cada elemento es del tipochar
. (Para obtener información sobre las matrices, vea Introducción a la programación web ASP.NET mediante la sintaxis Razor.)Ejecute la página en un explorador. Se muestran los datos especificados para los ejemplos anteriores.
Sugerencia
Mostrar datos de un archivo delimitado por comas de Microsoft Excel
Puede usar Microsoft Excel para guardar los datos contenidos en una hoja de cálculo como un archivo delimitado por comas (.csv archivo.) Cuando lo hace, el archivo se guarda en texto sin formato, no en formato de Excel. Cada fila de la hoja de cálculo está separada por un salto de línea en el archivo de texto y cada elemento de datos está separado por una coma. Puede usar el código que se muestra en el ejemplo anterior para leer un archivo delimitado por comas de Excel simplemente cambiando el nombre del archivo de datos en el código.
Eliminar archivos
Para eliminar archivos de su sitio web, puede usar el método File.Delete
. Este procedimiento muestra cómo permitir que los usuarios eliminen una imagen (.jpg archivo) de una imágenes carpeta si conocen el nombre del archivo.
Nota:
Importante En un sitio web de producción, normalmente restringe quién puede realizar cambios en los datos. Para obtener información sobre cómo configurar la pertenencia y sobre las formas de autorizar a los usuarios a realizar tareas en el sitio, vea Agregar seguridad y pertenencia a un sitio de ASP.NET Web Pages.
En el sitio web, cree una subcarpeta denominada imágenes.
Copie uno o varios archivos .jpg en la carpeta imágenes.
En la raíz del sitio web, cree un nuevo archivo denominado FileDelete.cshtml.
Reemplace el contenido existente por lo siguiente:
@{ bool deleteSuccess = false; var photoName = ""; if (IsPost) { photoName = Request["photoFileName"] + ".jpg"; var fullPath = Server.MapPath("~/images/" + photoName); if (File.Exists(fullPath)) { File.Delete(fullPath); deleteSuccess = true; } } } <!DOCTYPE html> <html> <head> <title>Delete a Photo</title> </head> <body> <h1>Delete a Photo from the Site</h1> <form name="deletePhoto" action="" method="post"> <p>File name of image to delete (without .jpg extension): <input name="photoFileName" type="text" value="" /> </p> <p><input type="submit" value="Submit" /></p> </form> @if(deleteSuccess) { <p> @photoName deleted! </p> } </body> </html>
Esta página contiene un formulario donde los usuarios pueden escribir el nombre de un archivo de imagen. No escriben la extensión .jpg nombre de archivo; al restringir el nombre de archivo como este, ayuda a evitar que los usuarios eliminen archivos arbitrarios en su sitio.
El código lee el nombre de archivo que el usuario ha escrito y, a continuación, construye una ruta de acceso completa. Para crear la ruta de acceso, el código usa la ruta de acceso del sitio web actual (tal como devuelve el método
Server.MapPath
), las imágenes nombre de carpeta, el nombre que ha proporcionado el usuario y ".jpg" como una cadena literal.Para eliminar el archivo, el código llama al método
File.Delete
, pasando la ruta de acceso completa que acaba de construir. Al final del marcado, el código muestra un mensaje de confirmación de que se eliminó el archivo.Ejecute la página en un explorador.
Escriba el nombre del archivo que se va a eliminar y haga clic en Enviar. Si se eliminó el archivo, el nombre del archivo se muestra en la parte inferior de la página.
Permitir que los usuarios carguen un archivo
El FileUpload
asistente permite a los usuarios cargar archivos en su sitio web. En el procedimiento siguiente se muestra cómo permitir que los usuarios carguen un único archivo.
Agregue la biblioteca de asistentes web de ASP.NET a su sitio web como se describe enInstalación de asistentes en un sitio de ASP.NET Web Pages, si no lo agréguelo anteriormente.
En la carpeta App_Data, cree una carpeta y asígnela el nombre UploadedFiles.
En la raíz, cree un nuevo archivo denominado FileUpload.cshtml.
Reemplace el contenido existente de la página por lo siguiente:
@using Microsoft.Web.Helpers; @{ var fileName = ""; if (IsPost) { var fileSavePath = ""; var uploadedFile = Request.Files[0]; fileName = Path.GetFileName(uploadedFile.FileName); fileSavePath = Server.MapPath("~/App_Data/UploadedFiles/" + fileName); uploadedFile.SaveAs(fileSavePath); } } <!DOCTYPE html> <html> <head> <title>FileUpload - Single-File Example</title> </head> <body> <h1>FileUpload - Single-File Example</h1> @FileUpload.GetHtml( initialNumberOfFiles:1, allowMoreFilesToBeAdded:false, includeFormTag:true, uploadText:"Upload") @if (IsPost) { <span>File uploaded!</span><br/> } </body> </html>
La parte del cuerpo de la página usa el
FileUpload
asistente para crear el cuadro de carga y los botones que probablemente esté familiarizado con:Las propiedades que establezca para el
FileUpload
asistente especifican que desea que un único cuadro para que el archivo se cargue y que desee que el botón enviar lea Cargar. (Agregará más cuadros más adelante en el artículo.)Cuando el usuario hace clic en Cargar, el código de la parte superior de la página obtiene el archivo y lo guarda. El
Request
objeto que se usa normalmente para obtener valores de los campos de formulario también tiene unaFiles
matriz que contiene el archivo (o archivos) que se han cargado. Puede obtener archivos individuales de posiciones específicas en la matriz; por ejemplo, para obtener el primer archivo cargado, obtendráRequest.Files[0]
, para obtener el segundo archivo, obtendráRequest.Files[1]
, etc. (Recuerde que en la programación, el recuento suele comenzar en cero.)Al capturar un archivo cargado, lo coloca en una variable (aquí,
uploadedFile
) para que pueda manipularlo. Para determinar el nombre del archivo cargado, solo tiene que obtener su propiedadFileName
. Sin embargo, cuando el usuario carga un archivo,FileName
contiene el nombre original del usuario, que incluye toda la ruta de acceso. Podría tener este aspecto:C:\Users\Public\Sample.txt
Sin embargo, no quiere toda esa información de ruta de acceso, ya que esa es la ruta de acceso en el equipo del usuario, no para el servidor. Solo quiere el nombre de archivo real (Sample.txt). Puede quitar solo el archivo de una ruta de acceso mediante el método
Path.GetFileName
, de la siguiente manera:Path.GetFileName(uploadedFile.FileName)
El objeto
Path
es una utilidad que tiene varios métodos como este que puede usar para quitar rutas de acceso, combinar rutas de acceso, etc.Una vez que haya obtenido el nombre del archivo cargado, puede crear una nueva ruta de acceso para dónde desea almacenar el archivo cargado en su sitio web. En este caso, combinará
Server.MapPath
, los nombres de carpeta (App_Data/UploadedFiles), y el nombre de archivo recién eliminado para crear una nueva ruta de acceso. A continuación, puede llamar al métodoSaveAs
del archivo cargado para guardar realmente el archivo.Ejecute la página en un explorador.
Haga clic en Examinar y, a continuación, seleccione un archivo para cargarlo.
El cuadro de texto situado junto al botón Examinar contendrá la ruta de acceso y la ubicación del archivo.
Haga clic en Cargar.
En el sitio web, haga clic con el botón derecho en la carpeta del proyecto y, a continuación, haga clic en Actualizar.
Abra la carpeta UploadedFiles. El archivo que cargó se encuentra en la carpeta.
Permitir que los usuarios carguen varios archivos
En el ejemplo anterior, permite que los usuarios carguen un archivo. Pero puede usar el FileUpload
asistente para cargar más de un archivo a la vez. Esto resulta útil para escenarios como cargar fotos, donde cargar un archivo a la vez es tedioso. (Puede leer sobre cómo cargar fotos en Trabajar con imágenes en un sitio de ASP.NET Web Pages.) En este ejemplo se muestra cómo permitir que los usuarios carguen dos a la vez, aunque puede usar la misma técnica para cargar más de eso.
Agregue la biblioteca de asistentes web de ASP.NET a su sitio web, tal como se describe en Instalación de asistentes en un sitio de ASP.NET Web Pages, si aún no lo ha hecho.
Cree una nueva página denominada FileUploadMultiple.cshtml.
Reemplace el contenido existente de la página por lo siguiente:
@using Microsoft.Web.Helpers; @{ var message = ""; if (IsPost) { var fileName = ""; var fileSavePath = ""; int numFiles = Request.Files.Count; int uploadedCount = 0; for(int i =0; i < numFiles; i++) { var uploadedFile = Request.Files[i]; if (uploadedFile.ContentLength > 0) { fileName = Path.GetFileName(uploadedFile.FileName); fileSavePath = Server.MapPath("~/App_Data/UploadedFiles/" + fileName); uploadedFile.SaveAs(fileSavePath); uploadedCount++; } } message = "File upload complete. Total files uploaded: " + uploadedCount.ToString(); } } <!DOCTYPE html> <html> <head><title>FileUpload - Multiple File Example</title></head> <body> <form id="myForm" method="post" enctype="multipart/form-data" action=""> <div> <h1>File Upload - Multiple-File Example</h1> @if (!IsPost) { @FileUpload.GetHtml( initialNumberOfFiles:2, allowMoreFilesToBeAdded:true, includeFormTag:true, addText:"Add another file", uploadText:"Upload") } <span>@message</span> </div> </form> </body> </html>
En este ejemplo, el
FileUpload
asistente en el cuerpo de la página está configurado para permitir que los usuarios carguen dos archivos de forma predeterminada. DadoallowMoreFilesToBeAdded
que se establece entrue
, el asistente representa un vínculo que permite al usuario agregar más cuadros de carga:Para procesar los archivos que carga el usuario, el código usa la misma técnica básica que usó en el ejemplo anterior: obtenga un archivo de
Request.Files
y guárdelo. (Incluye los distintos aspectos que debe hacer para obtener el nombre de archivo y la ruta de acceso correctos.) La innovación en este momento es que el usuario podría cargar varios archivos y no conoce muchos. Para averiguarlo, puede obtenerRequest.Files.Count
.Con este número a mano, puede recorrer en bucle
Request.Files
, capturar cada archivo a su vez y guardarlo. Cuando desee recorrer un número conocido de veces a través de una colección, puede usar unfor
bucle, como este:for(int i =0; i < numFiles; i++) { var uploadedFile = Request.Files[i]; if (uploadedFile.ContentLength > 0) { fileName = Path.GetFileName(uploadedFile.FileName); // etc. }
La variable
i
es simplemente un contador temporal que pasará de cero a cualquier límite superior que establezca. En este caso, el límite superior es el número de archivos. Pero dado que el contador se inicia en cero, como es habitual para los escenarios de recuento en ASP.NET, el límite superior es realmente uno menor que el recuento de archivos. (Si se cargan tres archivos, el recuento es cero a 2.)La
uploadedCount
variable totaliza todos los archivos que se cargan y guardan correctamente. Este código tiene en cuenta la posibilidad de que un archivo esperado no pueda cargarse.Ejecute la página en un explorador. El explorador muestra la página y sus dos cuadros de carga.
Seleccione dos archivos para cargar.
Haga clic en Agregar otro archivo. La página muestra un nuevo cuadro de carga.
Haga clic en Cargar.
En el sitio web, haga clic con el botón derecho en la carpeta del proyecto y, a continuación, haga clic en Actualizar.
Abra la carpeta UploadedFiles para ver los archivos cargados correctamente.