2010-01-22 12 views
5

Sur un site ASP.net sur mon lieu de travail, le bloc de code suivant est responsable du traitement des téléchargements de fichiers (NOTE: Response.TransmitFile n'est pas utilisé ici car le contenu du téléchargement est transmis en ligne à partir d'un fichier zip):Utilisation de la mémoire ASP.net lors du téléchargement

private void DownloadFile(Stream stream) 
{ 
     int bytesRead; 
     int chunkSize = 1048576; //1MB 

     byte[] readBuffer = new byte[chunkSize]; 
     while ((bytesRead = stream.Read(readBuffer, 0, readBuffer.Length)) != 0) 
      { 
       if(!Response.IsClientConnected) 
        break; 
       byte[] chunk = new byte[bytesRead]; 
       Array.Copy(readBuffer,0,chunk,0,bytesRead); 
       Response.BinaryWrite(chunk); 
       Response.Flush(); 
     } 
     stream.Close(); 
} 

Nos utilisateurs téléchargent fréquemment fichiers de plusieurs centaines de Mo, qui panse la mémoire du serveur assez rapide. Mon hypothèse est que cela est dû à la mise en mémoire tampon des réponses. Cela a-t-il du sens?

Je viens de lire à propos de la propriété 'buffer' de l'objet Response. Si je le mets à false, cela empêchera-t-il les appels Response.BinaryWrite() de mettre en mémoire tampon les données en mémoire? En général, quel est un bon moyen de limiter l'utilisation de la mémoire dans cette situation? Peut-être devrais-je diffuser du fichier zip vers un fichier temporaire, puis appeler Response.TransmitFile()?

EDIT: En plus des solutions possibles, je suis très intéressé par les explications du problème d'utilisation de la mémoire présent dans le code ci-dessus. Pourquoi cela consomme-t-il beaucoup plus de 1 Mo, même si Response.Flush est appelé à chaque itération de boucle? Est-ce juste l'allocation de tas inutile qui se produit à chaque itération de boucle (et qui n'obtient pas GC'd tout de suite), ou y at-il quelque chose d'autre au travail?

Répondre

4

Voici un code sur lequel je travaille pour cela. Il utilise un tampon de 8 000 octets pour envoyer le fichier en morceaux. Certains tests informels sur un gros fichier ont montré une diminution significative de la mémoire allouée.

int BufferSize = 8000; 
FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read); 
try { 
    long fileSize = stream.Length; 

    long dataLeftToRead = fileSize; 
    int chunkLength; 
    buffer = new Byte[BufferSize]; 

    while (dataLeftToRead > 0) { 
    if (!Response.IsClientConnected) { 
     break; 
    } 
    chunkLength = stream.Read(buffer, 0, BufferSize); 

    Response.OutputStream.Write(buffer, 0, chunkLength); 
    Response.Flush(); 

    dataLeftToRead -= chunkLength; 
    } 
} 
finally { 
    if (stream != null) { 
    stream.Close(); 
} 

modifié pour corriger une erreur de syntaxe et une valeur manquante

+0

pédant commentaire: 8k = 8192 octets; –

+0

thanx - fixed - nous les geeks doivent être scrupuleusement précis – Ray

+2

Quelle est la différence entre l'utilisation de Response.Write et l'écriture directe dans l'objet Response.OutputStream? – Odrade