2010-04-02 18 views
23

Estoy haciendo pruebas con HttpHandler de ASP.NET para descargar un archivo escribiendo directamente en la secuencia de respuesta, y no estoy muy seguro de la forma en que lo estoy haciendo. Se trata de un método de ejemplo, en el futuro, el archivo puede ser almacenado en un BLOB en la base de datos:Algunas preguntas sobre escribir en la corriente de respuesta ASP.NET

 public void GetFile(HttpResponse response) 
    { 
     String fileName = "example.iso"; 
     response.ClearHeaders(); 
     response.ClearContent(); 
     response.ContentType = "application/octet-stream"; 
     response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName); 
     using (FileStream fs = new FileStream(Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data"), fileName), FileMode.Open)) 
     { 
      Byte[] buffer = new Byte[4096]; 
      Int32 readed = 0; 

      while ((readed = fs.Read(buffer, 0, buffer.Length)) > 0) 
      { 
       response.OutputStream.Write(buffer, 0, readed); 
       response.Flush(); 
      } 
     } 
    } 

Pero, no estoy seguro de si esto es correcto o hay una mejor manera de hacerlo. Mis preguntas son:

  1. Al abrir la URL con el navegador, aparece el cuadro de diálogo "Guardar archivo" ... pero parece que el servidor ha comenzado ya a enviar datos en la corriente antes de que haga clic en "Guardar ", ¿eso es normal?
  2. Si elimino la línea "response.Flush()", cuando abro la URL con el navegador, ... veo cómo el servidor web está presionando datos pero no aparece el cuadro de diálogo "Guardar archivo", (o al menos no de manera razonable) ¿por qué?
  3. Cuando abro la url con un objeto WebRequest, veo que HttpResponse.ContentLength es "-1", aunque puedo leer la secuencia y obtener el archivo. ¿Cuál es el significado de -1? ¿Cuándo va HttpResponse.ContentLength a mostrar la duración de la respuesta? Por ejemplo, tengo un método que recupera un gran xml comprimido con desinflar como una secuencia binaria, pero en ese caso ... cuando accedo a él con una WebRequest, en HttpResponse puedo ver la longitud del contenido con la longitud de la secuencia , ¿por qué?
  4. ¿Cuál es la longitud óptima para la matriz Byte [] que uso como buffer para un rendimiento óptimo en un servidor web? He leído que está entre 4K y 8K ... pero qué factores debería considerar para tomar la decisión correcta.
  5. ¿Influye este método en el uso de la memoria de IIS o del cliente? ¿o está realmente almacenando en búfer la transferencia correctamente?

Lo siento por tantas preguntas, soy bastante nuevo en el desarrollo web: P

Saludos.

+1

También debería echar un vistazo a las implementaciones de Boilerplate HttpHandler aquí (http://haacked.com/archive/2005/03/17/AnAbstractBoilerplateHttpHandler.aspx) y aquí (http://www.hanselman.com /blog/PermaLink,guid,5c59d662-b250-4eb2-96e4-f274295bd52e.aspx). – R0MANARMY

+0

Se aprecia su forma de aprender. Sigue adelante . –

+0

Esto funcionará: [http://stackoverflow.com/questions/3362849/outofmemoryexception-when-send-big-file-500mb-using-filestream-aspnet][1] [ 1]: http://stackoverflow.com/questions/3362849/outofmemoryexception-when-send-big-file-500mb-using-filestream-aspnet –

Respuesta

16
  1. Sí; esto es normal.
  2. Si nunca se vacia, el navegador no obtiene ninguna respuesta hasta que finalice el proceso (ni siquiera el encabezado Content-Disposition). Por lo tanto, no sabe mostrar un cuadro de diálogo de archivo.
  3. El encabezado Content-Length solo se configura si toda la respuesta está almacenada en el búfer (si nunca se vacía) o si la configuró usted mismo. En este caso, puede y debe configurarlo usted mismo; escriba

    response.AppendHeader("Content-Length", new FileInfo(path).Length.ToString()); 
    
  4. Recomiendo 4K; No tengo ninguna base dura para la recomendación.
  5. Este método es la mejor manera de hacerlo. Llamando Flush dentro del bucle, está enviando la respuesta por el cable inmediatamente, sin ningún almacenamiento en búfer. Sin embargo, para un mayor rendimiento, puede usar la compresión GZIP.
+0

Gracias a todos, borran todas mis dudas. Me alegro de haberme unido a esta comunidad: D – vtortola

2
  1. Sí, es el almacenamiento en búfer.
  2. Flush empuja el contenido en caché al navegador. Si nunca se presiona, no obtendrá un cuadro de diálogo para guardar.
  3. Difícil de ver sin ver los archivos exactos/URL/secuencias que está utilizando.
  4. Creo que los factores dependen de qué tan lenta es tu página, realmente. Tendrás un mejor rendimiento hacia 4k. Y tal vez, el valor más bajo será mejor para acomodar conexiones más lentas.
  5. Ver # 1 & 2.
+0

Gracias a todos, borran todas mis dudas. Me alegro de haberme unido a esta comunidad: D – vtortola

2

Para # 3 que hay que configurar el encabezado de longitud de contenido en su http-respuesta. Muchos de esos valores provienen de encabezados http.

Creo que puede cambiar el almacenamiento intermedio cambiando una propiedad de almacenamiento en búfer en el objeto de respuesta a falso. No lo he hecho hace tiempo, así que no recuerdo lo que podría ser.

+0

Gracias a todos, aclaran todas mis dudas. Me alegro de haberme unido a esta comunidad: D – vtortola

Cuestiones relacionadas