PRB: Response.WriteFile no puede descargar un archivo grande

Seleccione idioma Seleccione idioma
Id. de artículo: 812406 - Ver los productos a los que se aplica este artículo
Aviso
Los productos de terceros descritos en este artículo están fabricados por proveedores independientes de Microsoft. Microsoft no otorga ninguna garantía, implícita o de otro tipo, con respecto al rendimiento o la confiabilidad de estos productos.
Expandir todo | Contraer todo

En esta página

Síntomas

Cuando intenta usar el método Response.WriteFile para descargar un archivo grande, la descarga puede no responder y, entonces, puede aparecer uno de los siguientes mensajes de error:
No se puede mostrar la página
O bien
Aplicación de servidor no disponible

La aplicación Web a la que está intentando obtener acceso en este servidor Web no está disponible en este momento. Presione el botón "Actualizar" del explorador Web para reintentar la solicitud.

Nota para administradores: en el registro de sucesos del sistema se puede encontrar un mensaje de error que detalla la causa de este error específico de la solicitud. Revise esta entrada del registro para descubrir lo que ocasionó este error.
También puede recibir el mensaje siguiente en el registro de sucesos de aplicación:

Aspnet_wp.exe (o W3wp.exe, en las aplicaciones que se ejecutan en Servicios de Microsoft Internet Information Server [IIS] 6.0) se detuvo inesperadamente.

Durante este proceso, también puede apreciar un incremento en la utilización de la memoria del servidor Web.

Causa

La configuración de hardware del equipo servidor Web determina el tamaño de archivo máximo que puede descargar correctamente. Cuando el proceso de trabajo de ASP.NET (Aspnet_wp.exe, o W3wp.exe en las aplicaciones que se ejecutan en Servicios de Microsoft Internet Information Server [IIS] 6.0) ejecuta la solicitud de descarga, el cuadro de dialogo de descarga aparece. El proceso de trabajo ASP.NET se inicia para enviar los datos al proceso de Servicios de Microsoft Internet Information Server (Inetinfo.exe o Dllhost.exe). No espera a que haga clic en Aceptar.

En función de la configuración del equipo, el proceso de IIS puede procesar los datos o los datos pueden almacenarse en memoria. Cuando el archivo es grande, los datos se almacenan en la memoria durante la comunicación entre estos dos procesos. Esto puede ocasionar un incremento en la utilización de la memoria del servidor Web. El error se debe a las restricciones de memoria en el servidor Web.

Solución

Para evitar este problema, utilice cualquiera de los métodos siguientes:
  • Obtenga los datos en fragmentos pequeños y muévalos a la secuencia de salida para descargarlos. En el código siguiente se demuestra cómo hacer esto.

    Importante: cuando establece el valor del atributo debug del elemento de compilación en false en el archivo Web.config de la aplicación .NET, debe establecer la propiedad Server.ScriptTimeout en un valor apropiado para el tamaño de la descarga del archivo. De manera predeterminada, el valor Server.ScriptTimeout está establecido en 90 segundos. Sin embargo, cuando el atributo debug se establece en true, el valor Server.ScriptTimeout se establecerá en un valor muy grande: 30.000.000 segundos. Como desarrollador, debe ser consciente de los efectos que esto puede tener en el comportamiento de la aplicación Web ASP.NET.

    Además, en el código que sigue debe tener en cuenta los valores de los parámetros que se usan con el constructor FileStream. Los valores de la enumeración que se especifican tienen una repercusión significativa en la funcionalidad que se proporciona. Para obtener más información, consulte el vínculo FileStream en la sección REFERENCIAS:
    Código de Visual Basic .NET
          Dim iStream As System.IO.Stream
    
          ' Búfer para leer 10 KB en el fragmento: Dim buffer(10000) As Byte
    
          ' Longitud del archivo: Dim length As Integer
    
          ' Número total de bytes que leer: Dim dataToRead As Long
    
          ' Identificar el archivo que descargar, incluyendo su ruta de acceso. Dim filepath As String = "DownloadFileName"
    
          ' Identificar el nombre de archivo. Dim filename As String = System.IO.Path.GetFileName(filepath)
    
          Try ' Open the file. iStream = New System.IO.FileStream(filepath, System.IO.FileMode.Open, _ IO.FileAccess.Read, IO.FileShare.Read)
    
             ' Número total de bytes que leer: dataToRead = iStream.Length
             
             Response.ContentType = "application/octet-stream" Response.AddHeader("Content-Disposition", "attachment; filename=" & filename)
    
             ' Leer los bytes. While dataToRead > 0 ' Comprobar que el cliente está conectado. If Response.IsClientConnected Then ' Leer los datos del búfer length = iStream.Read(buffer, 0, 10000)
    
                        ' Escribir los datos en la secuencia de salida actual. Response.OutputStream.Write(buffer, 0, length)
    
                        ' Vaciar los datos en la salida HTML. Response.Flush()
    
                        ReDim buffer(10000) ' Limpiar el búfer dataToRead = dataToRead - length Else 'Impedir un bucle infinito si el usuario se desconecta dataToRead = -1 End If End While
    
          Catch ex As Exception ' Capturar el error, si lo hay. Response.Write("Error : " & ex.Message) Finally If IsNothing(iStream) = False Then ' Cerrar el archivo. iStream.Close() End If End Try 
    Visual C# .NET Code
    	System.IO.Stream iStream = null;
    
    	// Búfer para leer 10 KB en el fragmento: byte[] buffer = new Byte[10000];
    
    	// Longitud del archivo: int length;
    
    	// Número total de bytes que leer: long dataToRead;
    
    	// Identificar el archivo que descargar incluyendo su ruta de acceso. string filepath  = "DownloadFileName";
    
    	// Identificar el nombre de archivo. string  filename  = System.IO.Path.GetFileName(filepath);
    
    	try { // Abrir el archivo. iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read,System.IO.FileShare.Read);
    
    
    		// Número total de bytes que leer: dataToRead = iStream.Length;
    
    		Response.ContentType = "application/octet-stream"; Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
    
    		// Leer los bytes. while (dataToRead > 0) { // Comprobar que el cliente está conectado. if (Response.IsClientConnected) { // Read the data in buffer. length = iStream.Read(buffer, 0, 10000);
    
    				// Escribir los datos en la secuencia de salida actual. Response.OutputStream.Write(buffer, 0, length);
    
    				// Vaciar los datos en la salida HTML. Response.Flush();
    
    				buffer= new Byte[10000]; dataToRead = dataToRead - length; } else { //impedir un bucle infinito si el usuario se desconecta dataToRead = -1; } } } catch (Exception ex) { // Capturar el error, si lo hay. Response.Write("Error : " + ex.Message); } finally { if (iStream != null) { //Cerrar el archivo. iStream.Close(); } } 
    Reemplazar DownloadFileName con el nombre de un archivo mayor de 100 megabytes (MB).

    O bien
  • Proporcione un vínculo para que el usuario descargue el archivo.

    O bien
  • Use Microsoft ASP 3.0 para las descargas o use Software Artisans FileUp con ASP.

    O bien
  • Cree una extensión ISAPI para descargar el archivo.

    O bien
  • Use FTP para descargar el archivo.

Estado

Este comportamiento es una característica del diseño de la aplicación.

Más información

Pasos para reproducir este comportamiento

  1. En Microsoft Visual Basic .NET o Microsoft Visual C# .NET, cree un nuevo proyecto de aplicación Web. De manera predeterminada, se crea WebForm1.aspx.
  2. Arrastre un objeto button del cuadro de herramientas a WebForm1.aspx.
  3. Haga doble clic en el objeto button para abrir el evento Click en la Vista Código.
  4. Pegue el código siguiente en el evento Click de Button1.

    Código de Visual Basic .NET
    	' Identificar el archivo que descargar, incluyendo su ruta de acceso. Dim filepath As String = DownloadFileName
    
    	' Identificar el nombre de archivo. Dim filename As String = System.IO.Path.GetFileName(filepath)
    
    	Response.Clear()
    	
    	' Especificar el tipo del archivo descargable. Response.ContentType = "application/octet-stream"
    
    	' Establecer el nombre de archivo predeterminado en el cuadro de diálogo FileDownload. Response.AddHeader("Content-Disposition", "attachment; filename=""" & filename & """")
    
    	Response.Flush()
    
    	' Descargar el archivo. Response.WriteFile(filepath)

    Código de Visual C# .NET
    	// Identificar el archivo que descargar incluyendo su ruta de acceso. string filepath  = DownloadFileName;
    
    	// Identificar el nombre de archivo. string  filename  = System.IO.Path.GetFileName(filepath);
    
    	Response.Clear()
    
    	// Especificar el tipo del archivo descargable. Response.ContentType = "application/octet-stream";
    
    	// Establecer el nombre de archivo predeterminado en el cuadro de diálogo FileDownload. Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
    
    	Response.Flush();
    
    	// Descargar el archivo. Response.WriteFile(filepath);
  5. Reemplace DownloadFileName con el nombre de un archivo mayor de 100 MB.
  6. En el menú Depurar, haga clic en Iniciar.
  7. Haga clic en Button1.

Referencias

Para obtener información adicional al respecto, haga clic en los números de artículo siguientes para verlos en Microsoft Knowledge Base:
307603 CÓMO: Escribir archivos binarios en el explorador utilizando ASP.NET y Visual Basic .NET
306654 CÓMO: Escribir archivos binarios en el explorador utilizando ASP.NET y Visual C# .NET
Para obtener más información, visite el siguiente sitio Web de Microsoft Developer Network (MSDN):
http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemIOFileStreamClassTopic.asp?frame=true

Propiedades

Id. de artículo: 812406 - Última revisión: viernes, 16 de junio de 2006 - Versión: 3.4
La información de este artículo se refiere a:
  • Microsoft Web Services Enhancements for Microsoft .NET 1.1
  • Microsoft ASP.NET 1.1
  • Microsoft ASP.NET 1.0
Palabras clave: 
kbwebserver kbwebforms kbweb kbdownload kbprb KB812406
Renuncia a responsabilidad de los contenidos de la KB sobre productos a los que ya no se ofrece asistencia alguna
El presente artículo se escribió para productos para los que Microsoft ya no ofrece soporte técnico. Por tanto, el presente artículo se ofrece "tal cual" y no será actualizado.

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com