2010-02-01 29 views
9

Aquí está la disposición:Descargas de gran tamaño utilizando C# y IIS 7

  • 1 servidor web que se ejecuta una aplicación de C# para el que mis usuarios (almacenados en una base de datos MySQL en dicho servidor) autenticar.

  • 1 servidor de archivos que ejecuta el software TBD. En el pasado, he utilizado lighttpd y mod_secdownload para proteger los archivos en los servidores de archivos, y funcionó bien (ish).

Me pregunto si hay una manera de hacerlo con una combinación de IIS y C# .Net. Todos mis otros servidores están ejecutando ese combo, y simplificaría un poco las cosas si pudiera hacer lo mismo con los servidores de archivos. El truco es que los archivos que se alojan son grandes. He visto ejemplos de personas que usan una pequeña aplicación para crear un objeto FileStream, leer en el archivo y crear la respuesta HTTP a mano. Esto funciona, pero dado que estoy trabajando con archivos de más de 500 MB de tamaño, es lento como diablos. Y posiblemente tenga 300 usuarios golpeando la caja a la vez, solicitando archivos. Eso no es bueno.

Entonces, ¿alguien ve una forma de evitar esto? Intento crear un sistema más transparente, y si todos mis servidores ejecutan el mismo software/hardware, mi vida será mucho más simple. ¡Gracias de antemano por cualquier consejo que me des!

+0

Está su aplicación de C# ASP.NET * Webforms * o * * MVC? –

+0

La aplicación que los usuarios utilizan para autenticarse es una aplicación web C# .Net 3.5. –

Respuesta

6

¿Sabes qué? El artículo de KB es poo. Aquí está mi recomendación oficial:

public void StreamFile(string filePath) 
{ 
    string fileName = Path.GetFileName(filePath); 

    using (var fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) 
    { 
     var contentLength = fStream.Length; 

     if (Request.UserAgent.Contains("MSIE")) 
     { 
      Response.AddHeader("Content-Transfer-Encoding", "binary"); 
     } 

     Response.ContentType = "application/octet-stream"; 
     Response.AddHeader("Content-Length", contentLength.ToString()); 

     // Even though "Content-Disposition" should have an upper-case "d", as per http://www.ietf.org/rfc/rfc2183.txt 
     // IE fails to recognize this if the "d" is upper-cased. 
     Response.AddHeader("Content-disposition", "attachment; filename=" + fileName); 

     var buffer = new byte[8192]; 

     while (Response.IsClientConnected) 
     { 
      var count = fStream.Read(buffer, 0, buffer.Length); 
      if (count == 0) 
      { 
       break; 
      } 

      Response.OutputStream.Write(buffer, 0, count); 
      Response.Flush(); 
     } 
    } 

    Response.Close(); 
} 
+0

Después de intentarlo, me parece que todavía carga el archivo en la memoria. Al menos, me estaba quedando sin memoria excepciones cuando lo probé en un archivo de 1.5GB, y me cansé de esperar la descarga en una de 450MB. Estoy haciendo esto en una máquina de prueba, no en el servidor de archivos, por lo que la cantidad de memoria con la que tengo que trabajar es menor. Mis servidores de archivos tienen un montón de ram (creo que 24GB) pero me gustaría una solución que no requiera mucha tensión en el procesador o la memoria. Lighttpd hace esto usando las reglas mod_secdownload y URL rewrite, que son rápidas y económicas en ciclos/memoria. –

+0

@john: la forma en que leo el código en Reflector, ninguno de los métodos de MS para escribir archivos usa realmente pequeños búferes. Todos parecen asignar un solo buffer para todo el archivo. Algo de esto es bastante difícil de rastrear, así que tal vez me esté perdiendo algo. – Ray

+1

@Sheep Slapper: http://support.microsoft.com/kb/812406 – user7116

1

This thread tiene mi solución para mantener el uso de memoria mientras los usuarios están descargando archivos. Sin embargo, es probable que desee un búfer más grande que el que usa mi muestra.

+0

Después de leer ese hilo y el artículo de Soporte de Microsoft en la respuesta anterior, me dirijo en esa dirección para una solución temporal. Es mejor porque hay menos aplicaciones involucradas en el proceso, pero no es tan transparente en lo que está sucediendo. Ahora solo tengo que desarrollar una pequeña aplicación para implementarla y crear mi propia versión de mod_secdownload, ¡ya que la aplicación que valida a mis usuarios no está en los servidores de archivos! Gracias por la info! –

0

Si bien esto no es directamente aplicable ya que está utilizando MySql pero es algo a tener en cuenta (incluso podría estar disponible de forma gratuita mediante sql server 2008 express). Sql Server 2008 ofrece compatibilidad con Filestream, que le permite acceder a los archivos como si estuvieran directamente almacenados en la base de datos, pero en realidad residen en un servidor de archivos. Entonces la información en las otras publicaciones puede ayudarlo a llegar al usuario.

FILESTREAM Storage in SQL Server 2008

Cuestiones relacionadas