2009-10-02 23 views
5

Tengo un sitio donde un usuario puede descargar un archivo. Algunos archivos son extremadamente grandes (el más grande es 323 MB). Cuando lo pruebo para intentar descargar este archivo recibo una excepción de falta de memoria. La única forma que conozco para descargar el archivo está debajo. La razón por la que uso el código a continuación es porque la URL está codificada y no puedo permitir que el usuario se vincule directamente con el archivo. ¿Hay alguna otra forma de descargar este archivo sin tener que leer todo en una matriz de bytes?¿Mejor manera de descargar un archivo binario?

FileStream fs = new FileStream(context.Server.MapPath(url), FileMode.Open, 
                  FileAccess.Read); 
    BinaryReader br = new BinaryReader(fs); 
    long numBytes = new FileInfo(context.Server.MapPath(url)).Length; 
    byte[] bytes = br.ReadBytes((int) numBytes); 

    string filename = Path.GetFileName(url); 
    context.Response.Buffer = true; 
    context.Response.Charset = ""; 

    context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
    context.Response.ContentType = "application/x-rar-compressed"; 
    context.Response.AddHeader("content-disposition", "attachment;filename=" + filename); 

    context.Response.BinaryWrite(bytes); 
    context.Response.Flush(); 
    context.Response.End(); 
+0

Haré la pregunta obvia: ¿puedes leer un fragmento fijo del BinaryReader en un bucle, escribiéndolo en Response.BinaryWrite? No veo ningún motivo por el que necesite leer todo el archivo en la memoria como una sola operación. – Joe

Respuesta

16

En lugar de

context.Response.BinaryWrite(bytes); 

uso

context.Response.TransmitFile(context.Server.MapPath(url)); 

Esto evitará leer el archivo en la memoria.

+1

gracias Peter! eso funcionó muy bien. –

3

intentar algo como esto:

using (var br = new BinaryReader(fs)) 
     { 

      FileStream toFile = File.OpenWrite(ToFileName); 
      byte[] buff = new byte[2000]; 
      while (reader.Read(buff, 0, 2000) > 0) 
      { 
       toFile.Write(buff, 0, 2000); 
       toFile.Flush(); 
      } 
     } 

Lo importante es que se utiliza un búfer más pequeño y vaciar la corriente de escritura para borrar la memoria.

En este momento está reteniendo todo el archivo que está descargando en su BinaryReader y BinaryWriter. Chunking la descarga en un búfer más pequeño alivia esta carga en la memoria.

Cuestiones relacionadas