Exportar (0) Imprimir
Expandir todo
Expandir Minimizar

Carga de archivos en ASP.NET 2.0

fecha de actualizacion o subtitulo

Publicado: 27 de Marzo de 2006

Por Bill Evjen
Reuters

Este artículo se aplica a:
Microsoft ASP.NET 2.0
Microsoft Visual Web Developer 2005 Express Edition

Resumen: aprenda a utilizar el nuevo control de servidor FileUpload de Microsoft ASP.NET 2.0. (15 páginas impresas.)

En esta página

Introducción Introducción
Un ejemplo del control de servidor FileUpload Un ejemplo del control de servidor FileUpload
Conclusión Conclusión
Acerca del autor Acerca del autor

Introducción

Desde la presentación de Microsoft ASP.NET 1.0, existe un medio incorporado para crear aplicaciones Web capaces de cargar archivos en el servidor de alojamiento. Esto se hacía mediante el control de servidor HTML File Field. Una vez escribí en MSDN un artículo acerca del uso eficaz de este control en aplicaciones de ASP.NET. En este artículo vuelvo a presentar el proceso de carga de archivos, pero no con el control File Field, sino con el nuevo control de servidor FileUpload incluido en ASP.NET 2.0.

Es importante señalar que, si bien en este artículo se presenta el nuevo control de servidor FileUpload, todavía es posible utilizar el control File Field en las aplicaciones.

Un ejemplo del control de servidor FileUpload

Al utilizar el control File Field en ASP.NET 1.x debía realizar unos pasos adicionales para que todo funcionara. Por ejemplo, era necesario que uno mismo agregara enctype="multipart/form-data" en el elemento <form> de la página. El nuevo control de servidor FileUpload incluido en ASP.NET 2.0 simplifica más que nunca el proceso de carga de archivos en el servidor de alojamiento.

Finalmente, está intentando otorgar acceso para programar la etiqueta HTML <input type="file">. Esta etiqueta se utiliza para trabajar con los datos de archivos en un formulario HTML. Anteriormente, al utilizar el ASP clásico (ASP 3.0 o anterior), muchos programadores trabajaban con componentes de terceros para cargar archivos del cliente en el servidor. Ahora, .NET y este nuevo control se encargan de eso. En el listado 1 se muestra cómo utilizar el control FileUpload para cargar archivos en el servidor.

Nota

El código de muestra se ofrece en Microsoft Visual Basic y C#.

Listado 1. Carga de archivos en el servidor mediante el control FileUpload

Visual Basic

<%@ Page Language="VB" %>

<script runat="server">
    Protected Sub Button1_Click(ByVal sender As Object, _
      ByVal e As System.EventArgs)
        If FileUpload1.HasFile Then
            Try
                FileUpload1.SaveAs("C:\Uploads\" & _
                   FileUpload1.FileName)
                Label1.Text = "File name: " & _
                   FileUpload1.PostedFile.FileName & "<br>" & _
                   "File Size: " & _
                   FileUpload1.PostedFile.ContentLength & " kb<br>" & _
                   "Content type: " & _
                   FileUpload1.PostedFile.ContentType
            Catch ex As Exception
                Label1.Text = "ERROR: " & ex.Message.ToString()
            End Try
        Else
            Label1.Text = "You have not specified a file."
        End If
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Upload Files</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:FileUpload ID="FileUpload1" runat="server" /><br />
        <br />
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" 
         Text="Upload File" />&nbsp;<br />
        <br />
        <asp:Label ID="Label1" runat="server"></asp:Label></div>
    </form>
</body>
</html>

C#

<%@ Page Language="C#" %>

<script runat="server">
    protected void Button1_Click(object sender, EventArgs e)
    {
        if (FileUpload1.HasFile)
            try
            {
                FileUpload1.SaveAs("C:\\Uploads\\" + 
                     FileUpload1.FileName);
                Label1.Text = "File name: " +
                     FileUpload1.PostedFile.FileName + "<br>" +
                     FileUpload1.PostedFile.ContentLength + " kb<br>" +
                     "Content type: " +
                     FileUpload1.PostedFile.ContentType;
            }
            catch (Exception ex)
            {
                Label1.Text = "ERROR: " + ex.Message.ToString();
            }
        else
        {
            Label1.Text = "You have not specified a file.";
        }
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Upload Files</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:FileUpload ID="FileUpload1" runat="server" /><br />
        <br />
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" 
         Text="Upload File" />&nbsp;<br />
        <br />
        <asp:Label ID="Label1" runat="server"></asp:Label></div>
    </form>
</body>
</html>

Al ejecutar esta página, observe el código fuente generado para la página. Este código fuente se muestra en el listado 2.

Listado 2. El código fuente generado a partir del control FileUpload

<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>
   Upload Files
</title></head>
<body>
    <form name="form1" method="post" action="MyFileUpload.aspx" 
     id="form1" enctype="multipart/form-data">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
value="/wEPDwUJNDcxNTg5NDg3D2QWAgIEDxYCHgdlbmN0eXBlBRNtdWx0aX
BhcnQvZm9yb
       S1kYXRhZGQUQEUFMY1+/fp1mnrkbqmVNQIzFA==" />
</div>

    <div>
        <input type="file" name="FileUpload1" id="FileUpload1" /><br />
        <br />
        <input type="submit" name="Button1" value="Upload File" 
         id="Button1" />&nbsp;<br />
        <br />
        <span id="Label1"></span>
    </div>
    
<div>

   <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" 
    value="/wEWAgLB+7jIAwKM54rGBv2Iz6LxVY7jWec0gZMxnuaK2ufq" />
</div></form>
</body>
</html>

Lo primero que salta a la vista es que, dado que el control FileUpload está en la página, ASP.NET 2.0 modificó el elemento <form> de la página por su cuenta al agregar el atributo enctype adecuado. También notará que el control FileUpload se convirtió en un elemento HTML <input type="file">.

Al ejecutar la página del listado 1, puede seleccionar un archivo y cargarlo en el servidor haciendo clic en el botón Cargar archivo de la página. En este ejemplo existen varios aspectos importantes que vale la pena comentar para que comprenda todas las piezas necesarias para que todo funcione. Para que el ejemplo del listado 1 funcione, debe permitir que la cuenta utilizada por ASP.NET escriba en la carpeta de destino del servidor y así poder guardar el archivo en la carpeta especificada.

Si cree que su cuenta de ASP.NET no está habilitada para escribir en la carpeta que desea, abra Microsoft Windows Explorer y vaya a la carpeta donde quiere agregar este permiso. Haga clic con el botón secundario del mouse en la carpeta (en este caso, la carpeta Uploads) y seleccione Propiedades. En el cuadro de diálogo Propiedades, haga clic en la ficha Seguridad y asegúrese de que la cuenta de equipo ASP.NET figure en la lista y tenga los permisos necesarios para escribir en el disco (consulte la figura 1).

Figura 1. La ficha Seguridad de la carpeta Uploads

Si no encuentra la cuenta de equipo ASP.NET en la ficha Seguridad, agréguela haciendo clic en el botón Agregar y escribiendo ASPNET (sin el punto) en el área de texto, como se muestra en la figura 2.

Figura 2. Incorporación de la cuenta de equipo ASP.NET en la definición de seguridad de la carpeta

Haga clic en Aceptar para agregar la cuenta de equipo ASP.NET a la lista. Allí asegúrese de otorgarle a la cuenta los permisos necesarios y haga clic en Aceptar.

El botón Enviar de la página genera el evento Button1_Click. Este evento carga el archivo y muestra un mensaje que indica si la carga se completó correctamente al presentar información sobre el archivo. Si la carga no fue correcta, en la página se muestra un mensaje de error con la descripción del problema.

Al utilizar el control FileUpload que se convierte en una etiqueta <input type="file">, el explorador coloca de forma automática un botón Examinar junto al campo de texto en la página de ASP.NET. No hace falta que programe nada más. Cuando el usuario final hace clic en el botón Examinar, puede explorar el sistema de archivos locales en busca del archivo que se cargará en el servidor. Esto se muestra en la figura 3. Al hacer clic en Abrir, se colocará el nombre del archivo y su ruta de acceso en el campo de texto.

Figura 3. Selección de un archivo

Limitaciones de tamaño de archivos

Quizás no lo note, pero existe un límite para el tamaño de los archivos que se pueden cargar mediante esta técnica. El límite predeterminado para los archivos que se cargan en el servidor con el control FileUpload es alrededor de 4 MB. No se puede cargar nada que supere ese límite.

Una de las grandes virtudes de .NET, no obstante, es que suele ofrecer alguna forma de superar las limitaciones. Por lo general, se puede modificar la configuración predeterminada. Para cambiar el límite de tamaño, debe realizar algunos cambios en el archivo web.config.comments (ubicado en la carpeta de configuración de ASP.NET 2.0, C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG) o web.config de su aplicación.

En el archivo web.config.comments, busque el nodo <httpRuntime>, que es similar a éste:

<httpRuntime 
 executionTimeout="110" 
 maxRequestLength="4096" 
 requestLengthDiskThreshold="80" 
 useFullyQualifiedRedirectUrl="false" 
 minFreeThreads="8" 
 minLocalRequestFreeThreads="4" 
 appRequestQueueLimit="5000" 
 enableKernelOutputCache="true" 
 enableVersionHeader="true" 
 requireRootedSaveAsPath="true" 
 enable="true" 
 shutdownTimeout="90" 
 delayNotificationTimeout="5" 
 waitChangeNotification="0" 
 maxWaitChangeNotification="0" 
 enableHeaderChecking="true" 
 sendCacheControlHeader="true" 
 apartmentThreading="false" />

En este nodo ocurren muchas cosas, pero la configuración que se encarga del tamaño de los archivo que se cargan es el atributo maxRequestLength. El valor predeterminado es 4096 kilobytes (KB). Simplemente modifique el valor para aumentar el tamaño límite. Si desea poder cargar archivos de 10 megabytes (MB) en el servidor, configure el valor maxRequestLength en 11264, lo cual significa que la aplicación permitirá cargar archivos de hasta 11.000 KB.

Este cambio en el archivo web.config.comments aplica la configuración a todas las aplicaciones del servidor. Si desea aplicarla sólo a la aplicación con la que está trabajando, aplique este nodo en el archivo web.config de su aplicación reemplazando la configuración del archivo web.config.comments. Asegúrese de que este nodo se encuentre entre los nodos <system.web> del archivo de configuración.

Otra configuración involucrada en la limitación de tamaño de los archivos es el valor del atributo executionTimeout del nodo <httpRuntime>

El valor del atributo executionTimeout es la cantidad de segundos de carga permitidos antes de que ASP.NET la termine. Si permitirá cargar archivos más grandes, deberá incrementar este valor además del de maxRequestLength.

Una desventaja de aumentar el tamaño permitido es que hay piratas informáticos que atacan servidores enviándoles una gran cantidad de solicitudes. Para protegerse de esto, puede reducir el tamaño permitido o, de lo contrario, descubrirá cientos y hasta miles de solicitudes de 10 MB en el servidor.

Validación en el cliente de los tipos de archivos que se pueden cargar

Existen varios métodos para controlar los tipos de archivos que se pueden cargar en el servidor. Desafortunadamente, ninguno es infalible para protegerlo de la carga de archivos malintencionados. Sin embargo, existen pasos para simplificar un poco este proceso de permitir que los usuarios finales carguen archivos.

Un buen método es utilizar los controles de validación ASP.NET incluidos de forma gratuita con ASP.NET. Estos controles permiten realizar comprobaciones de expresiones regulares en los archivos cargados para ver si la extensión está permitida.

Esto es ideal para los exploradores que permiten el uso de controles de validación por parte de los clientes ya que obliga al cliente a realizar la comprobación y el archivo no se carga en el servidor si la firma no está permitida. En el listado 3 se muestra un ejemplo de uso de los controles de validación para llevar esto a cabo.

Nota

Aquí no se explica el uso de controles de validación. Consulte Validating ASP.NET Server Controls (en inglés) para obtener una explicación completa de los controles de validación y cómo utilizarlos en las páginas de ASP.NET.

Listado 3. Uso de los controles de validación para restringir el tipo de archivos cargados en el servidor

<asp:FileUpload ID="FileUpload1" runat="server" /><br />
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" 
 Text="Upload File" />&nbsp;<br />
<br />
<asp:Label ID="Label1" runat="server"></asp:Label>
<asp:RegularExpressionValidator 
 id="RegularExpressionValidator1" runat="server" 
 ErrorMessage="Only mp3, m3u or mpeg files are allowed!" 
 ValidationExpression="^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))
    +(.mp3|.MP3|.mpeg|.MPEG|.m3u|.M3U)$" 
 ControlToValidate="FileUpload1"></asp:RegularExpressionValidator>
<br />
<asp:RequiredFieldValidator 
 id="RequiredFieldValidator1" runat="server" 
 ErrorMessage="This is a required field!" 
 ControlToValidate="FileUpload1"></asp:RequiredFieldValidator>

Esta sencilla página de ASP.NET utiliza controles de validación para que el usuario final sólo pueda cargar archivos .mp3, .mpeg o .m3u en el servidor. Si se trata de otro tipo de archivo, un control Validation inicia una excepción en la pantalla. Esto se muestra en la figura 4.

Figura 4. Validación del tipo de archivo mediante controles de validación

Los controles Validation no son un método infalible para controlar qué archivos se cargan en el servidor. No es demasiado difícil sortear este sencillo modelo de seguridad. Basta con modificar la extensión de un archivo para que se lo acepte y se cargue en el servidor.

Validación de tipos de archivos en el servidor

Acaba de ver una forma sencilla de agregar controles de servidor de validación ASP.NET en su página de ASP.NET para que el cliente valide las extensiones de archivos (en forma de texto). Ahora veamos cómo realizar una operación similar en el servidor. Esto se muestra en el listado 4.

Listado 4. Comprobación del tipo de archivo en el servidor

Visual Basic

Protected Sub Button1_Click(ByVal sender As Object, _
      ByVal e As System.EventArgs)
        If FileUpload1.HasFile Then
            Dim fileExt As String
            fileExt = System.IO.Path.GetExtension(FileUpload1.FileName)
            
            If (fileExt = ".mp3") Then
                Try
                    FileUpload1.SaveAs("C:\Uploads\" & _
                       FileUpload1.FileName)
                    Label1.Text = "File name: " & _
                      FileUpload1.PostedFile.FileName & "<br>" & _
                      "File Size: " & _
                      FileUpload1.PostedFile.ContentLength & " kb<br>" & _
                      "Content type: " & _
                      FileUpload1.PostedFile.ContentType
                Catch ex As Exception
                    Label1.Text = "ERROR: " & ex.Message.ToString()
                End Try
            Else
                Label1.Text = "Only .mp3 files allowed!"
            End If
        Else
            Label1.Text = "You have not specified a file."
        End If
    End Sub

C#

    protected void Button1_Click(object sender, EventArgs e)
    {

        if (FileUpload1.HasFile)
        {
            string fileExt = 
               System.IO.Path.GetExtension(FileUpload1.FileName);

            if (fileExt == ".mp3")
            {
                try
                {
                    FileUpload1.SaveAs("C:\\Uploads\\" + 
                       FileUpload1.FileName);
                    Label1.Text = "File name: " +
                        FileUpload1.PostedFile.FileName + "<br>" +
                        FileUpload1.PostedFile.ContentLength + " kb<br>" +
                        "Content type: " +
                        FileUpload1.PostedFile.ContentType;
                }
                catch (Exception ex)
                {
                    Label1.Text = "ERROR: " + ex.Message.ToString();
                }
            }
            else
            {
                Label1.Text = "Only .mp3 files allowed!";
            }
        }
        else
        {
            Label1.Text = "You have not specified a file.";
        }
    }

Ahora, al utilizar el método GetExtension del espacio de nombres System.IO.Path, puede básicamente llevar a cabo la misma operación. Es importante señalar que esto no evita que el usuario final pueda modificar la extensión del archivo y cargarlo en el servidor de alojamiento.

Carga simultánea de varios archivos

Hasta aquí, hemos visto buenos ejemplos de cómo cargar un archivo en el servidor sin grandes inconvenientes. Ahora veamos cómo cargar en el servidor varios archivos de una misma página.

Microsoft .NET Framework no posee una función que permita cargar varios archivos desde una página de ASP.NET. De todas formas, con un poco de trabajo se puede lograr fácilmente al igual que en el pasado al utilizar .NET 1.x.

La clave es importar la clase System.IO en su página de ASP.NET y luego utilizar la clase HttpFileCollection para capturar todos los archivos enviados junto al objeto Request. Esto permite cargar todos los archivos que uno desee de una misma página.

Si lo desea, puede encargarse de cada control FileUpload de la página de forma individual, como se muestra en el listado 5.

Listado 5. Manejo individual de cada control FileUpload

Visual Basic

If FileUpload1.HasFile Then
   ' Handle file
End If

If FileUpload2.HasFile Then
   ' Handle file
End If

C#

if (FileUpload1.HasFile) {
   // Handle file
}

if (FileUpload2.HasFile) {
   // Handle file
}

Este método funciona, pero en muchas ocasiones querrá encargarse de estos archivos con la clase HttpFileCollection, en especial si trabaja con una lista de controles de servidor generada de forma dinámica.

Para ver un ejemplo de esto, puede crear una página de ASP.NET con tres controles FileUpload y un botón Enviar (mediante el control Button). Después de que el usuario hace clic en el botón Enviar y se envían los archivos al servidor, el código posterior toma los archivos y los guarda en una ubicación específica en el servidor. Tras guardar los archivos, la información enviada se presenta en la página de ASP.NET (consulte el listado 6).

Listado 6. Carga de varios archivos en el servidor

Visual Basic

Protected Sub Button1_Click(ByVal sender As Object, _
   ByVal e As System.EventArgs)

   Dim filepath As String = "C:\Uploads"
   Dim uploadedFiles As HttpFileCollection = Request.Files
   Dim i As Integer = 0

   Do Until i = uploadedFiles.Count
     Dim userPostedFile As HttpPostedFile = uploadedFiles(i)

     Try
        If (userPostedFile.ContentLength > 0) Then
           Label1.Text += "<u>File #" & (i + 1) & "</u><br>"
           Label1.Text += "File Content Type: " & _
              userPostedFile.ContentType & "<br>"
           Label1.Text += "File Size: " & _
              userPostedFile.ContentLength & "kb<br>"
           Label1.Text += "File Name: " & _
              userPostedFile.FileName & "<br>"

           userPostedFile.SaveAs(filepath & "\" & _
              System.IO.Path.GetFileName(userPostedFile.FileName))

           Label1.Text += "Location where saved: " & _
              filepath & "\" & _
              System.IO.Path.GetFileName(userPostedFile.FileName) & _
              "<p>"
        End If
     Catch ex As Exception
        Label1.Text += "Error:<br>" & ex.Message
     End Try
     i += 1
   Loop
End Sub

C#

protected void Button1_Click(object sender, EventArgs e)
{
   string filepath = "C:\\Uploads";
   HttpFileCollection uploadedFiles = Request.Files;
    
   for (int i = 0; i < uploadedFiles.Count; i++)
   {    
      HttpPostedFile userPostedFile = uploadedFiles[i];
    
      try
      {    
         if (userPostedFile.ContentLength > 0 )
         {
            Label1.Text += "<u>File #" + (i+1) + 
               "</u><br>";
            Label1.Text += "File Content Type: " + 
               userPostedFile.ContentType + "<br>";
            Label1.Text += "File Size: " + 
               userPostedFile.ContentLength + "kb<br>";
            Label1.Text += "File Name: " + 
               userPostedFile.FileName + "<br>";
    
            userPostedFile.SaveAs(filepath + "\\" + 
               System.IO.Path.GetFileName(userPostedFile.FileName));
    
            Label1.Text += "Location where saved: " + 
               filepath + "\\" + 
               System.IO.Path.GetFileName(userPostedFile.FileName) + 
               "<p>";
         }    
      } 
      catch (Exception Ex)
      {    
         Label1.Text += "Error: <br>" + Ex.Message;    
      }    
   }    
}

El usuario final puede seleccionar hasta cuatro archivos y hacer clic en el botón Cargar archivos, que inicializa el evento Button1_Click. Utilizar la clase HttpFileCollection con la propiedad Request.Files permite controlar todos los archivos cargados de la página. Cuando los archivos se encuentran en este estado, puede hacer lo que quiera con ellos. En este caso, las propiedades de los archivos se examinan y se escriben en la pantalla. Finalmente, los archivos se guardan en la carpeta Uploads del directorio raíz del servidor. En la figura 5 se ilustra el resultado de esta acción.

Figura 5. Carga simultánea de cuatro archivos de una página de ASP.NET en el servidor

Habrá notado que un aspecto interesante del ejemplo es que los cuadros de texto de entrada del estado de los archivos no se guardan junto a la devolución. Esto se puede ver en la figura 5. En ASP.NET, el cuadro de texto de entrada del estado de los archivos no puede guardarse porque esto constituiría un riesgo de seguridad.

Conclusión

El control de servidor FileUpload incluido en ASP.NET es un eficaz control bastante difícil de lograr en la época de Active Server Pages 3.0. Esta nueva función permite que los usuarios finales carguen más de un archivo en el servidor. Recuerde que puede controlar el tamaño de los archivos cargados modificando la configuración de los archivos web.config.comments o web.config.

Acerca del autor

Bill Evjen es un activo defensor de las tecnologías .NET y las iniciativas de aprendizaje basadas en la comunidad para .NET. Es director técnico de Reuters, la empresa internacional de servicios financieros e informativos ubicada en St. Louis, Missouri. Bill es fundador y director ejecutivo de International .NET Association (INETA), que representa a más de 100.000 miembros de todo el mundo. También es autor y orador y ha escrito varios libros como ASP.NET Professional Secrets, XML Web Services for ASP.NET, Web Services Enhancements y Visual Basic .NET Bible (todos disponibles en Wiley).

Mostrar:
© 2015 Microsoft