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.

  1. Cree una carpeta denominada App_Data, si aún no existe.

  2. En la raíz de su sitio web, cree un nuevo archivo denominado UserData.cshtml.

  3. 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 MapPathmétodo del objeto Server. 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) para MapPath. (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 del File 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.

    Screenshot of the browser window showing the First Name, Last Name, and Email text fields with a Submit button following them.

  • 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.

    Screenshot of the data dot t x t file showing the data entered into the web browser fields has been recorded into the t x t file.

  • 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.

  1. En el sitio web, realice una copia del archivoUserData.cshtml y asigne un nombre al UserDataMultiple.cshtml.

  2. 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, usa the AppendAllText método. Los métodos son similares, excepto que AppendAllText agrega los datos al final del archivo. Al igual que con WriteAllText, AppendAllText crea el archivo si aún no existe.

  3. Ejecute la página en un explorador.

  4. Escriba los valores de los campos y haga clic en Enviar.

  5. Agregue más datos y vuelva a enviar el formulario.

  6. Vuelva al proyecto, haga clic con el botón derecho en la carpeta del proyecto y, a continuación, haga clic en Actualizar.

  7. Abra el archivo data.txt. Ahora contiene los nuevos datos que acaba de escribir.

    Screenshot of the data dot t x t file showing the data entered into the web browser fields has been recorded without overwriting previous data.

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.

  1. En la raíz de su sitio web, cree un nuevo archivo denominado DisplayData.cshtml.

  2. 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étodo File.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 externo foreach 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étodo File.ReadAllLines devuelve datos como una matriz. El tipo de datos char es necesario porque el método Split devuelve un array en el que cada elemento es del tipo char. (Para obtener información sobre las matrices, vea Introducción a la programación web ASP.NET mediante la sintaxis Razor.)

  3. Ejecute la página en un explorador. Se muestran los datos especificados para los ejemplos anteriores.

    Screenshot of the browser window showing the data from the data from the data dot t x t file displayed in an array.

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.

  1. En el sitio web, cree una subcarpeta denominada imágenes.

  2. Copie uno o varios archivos .jpg en la carpeta imágenes.

  3. En la raíz del sitio web, cree un nuevo archivo denominado FileDelete.cshtml.

  4. 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.

  5. Ejecute la página en un explorador.

    Screenshot of the browser window showing the Delete a Photo from the Site page with a field for the file name and the Submit button.

  6. 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.

  1. 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.

  2. En la carpeta App_Data, cree una carpeta y asígnela el nombre UploadedFiles.

  3. En la raíz, cree un nuevo archivo denominado FileUpload.cshtml.

  4. 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:

    Screenshot of the File Upload web browser page showing the File Upload helper file picker and Upload button.

    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 una Files 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 propiedad FileName. 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étodo SaveAs del archivo cargado para guardar realmente el archivo.

  5. Ejecute la página en un explorador.

    Screenshot of the File Upload Single File Example web browser page showing the file picker and the Upload button.

  6. Haga clic en Examinar y, a continuación, seleccione un archivo para cargarlo.

    Screenshot of the File Explorer window showing a file selected and highlighted in blue and the Open button highlighted in a blue rectangle.

    El cuadro de texto situado junto al botón Examinar contendrá la ruta de acceso y la ubicación del archivo.

    Screenshot of the File Upload Single File Example web browser page showing the file picker with the selected file and the Upload button.

  7. Haga clic en Cargar.

  8. En el sitio web, haga clic con el botón derecho en la carpeta del proyecto y, a continuación, haga clic en Actualizar.

  9. Abra la carpeta UploadedFiles. El archivo que cargó se encuentra en la carpeta.

    Screenshot of the project folder hierarchy showing the Samples dot t x t file highlighted in blue inside of the Uploaded Files folder.

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.

  1. 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.

  2. Cree una nueva página denominada FileUploadMultiple.cshtml.

  3. 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. Dado allowMoreFilesToBeAdded que se establece en true, el asistente representa un vínculo que permite al usuario agregar más cuadros de carga:

    Screenshot of the File Upload Multiple File Example web browser page showing two file pickers and an Upload button.

    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 obtener Request.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 un for 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.

  4. Ejecute la página en un explorador. El explorador muestra la página y sus dos cuadros de carga.

  5. Seleccione dos archivos para cargar.

  6. Haga clic en Agregar otro archivo. La página muestra un nuevo cuadro de carga.

    Screenshot of the File Upload Multiple File Example web browser page showing two file pickers with selected files and an Upload button.

  7. Haga clic en Cargar.

  8. En el sitio web, haga clic con el botón derecho en la carpeta del proyecto y, a continuación, haga clic en Actualizar.

  9. Abra la carpeta UploadedFiles para ver los archivos cargados correctamente.

Recursos adicionales

Trabajar con imágenes en un sitio de ASP.NET Web Pages

Exportación a un archivo CSV