2010-06-21 10 views
19

J'ai une classe DocumentGenerator qui enveloppe un MemoryStream. J'ai donc implémenté IDisposable sur la classe.Comment puis-je disposer de mon flux de fichiers lors de l'implémentation d'un téléchargement de fichier dans ASP.NET?

Je ne peux pas voir comment/où je peux éventuellement le jeter.

Ceci est mon code actuel, qui effectue un téléchargement de fichier dans MVC:

using (DocumentGenerator dg = DocumentGenerator.OpenTemplate(path)) 
{ 
    /* some document manipulation with the 
     DocumentGenerator goes here ...*/ 

    return File(dg.GetDocumentStream(), "text/plain", filename); 
} 

Cette erreur que le flux est fermé/disposé avant que le contrôleur a fini avec elle. Comment puis-je m'assurer que mes ressources sont correctement éliminées dans cette situation?

EDIT: Mon implémentation de IDisposable actuellement ne dispose que du MemoryStream. Je sais que ce n'est pas une bonne implémentation, je l'ai juste utilisé comme test. Y a-t-il quelque chose de différent que je pourrais faire ici pour le faire fonctionner?

public void Dispose() 
{ 
    _ms.Dispose(); 
    _ms = null; 
} 
+1

Pouvez-vous nous montrer l'implémentation d'IDisposable, s'il vous plaît? – DHN

+0

Est-ce que '_ms' est le même que celui que vous obtenez après avoir appelé' GetDocumentStream'? –

+0

@ Jordão: oui c'est correct, d'où le problème. – fearofawhackplanet

Répondre

29

Vous n'avez pas besoin de disposer le cours d'eau. Il sera éliminé par la méthode FileStreamResult.WriteFile. Extrait du code de cette classe:

public FileStreamResult(Stream fileStream, string contentType) : base(contentType) 
{ 
    if (fileStream == null) 
    { 
     throw new ArgumentNullException("fileStream"); 
    } 
    this.FileStream = fileStream; 
} 

protected override void WriteFile(HttpResponseBase response) 
{ 
    Stream outputStream = response.OutputStream; 
    using (this.FileStream) 
    { 
     byte[] buffer = new byte[0x1000]; 
     while (true) 
     { 
      int count = this.FileStream.Read(buffer, 0, 0x1000); 
      if (count == 0) 
      { 
       return; 
      } 
      outputStream.Write(buffer, 0, count); 
     } 
    } 
} 

Notez que le using. Lorsque vous appelez File(dg.GetDocumentStream(), "text/plain", filename) à partir de votre contrôleur, cela appelle le constructeur qui stocke le flux dans une propriété publique qui est disposée pendant le rendu. Conclusion: vous n'avez pas besoin de vous préoccuper de la disposition du flux avec dg.GetDocumentStream().

+1

Que se passe-t-il si votre flux provient d'un autre objet jetable comme HttpWebResponse? Devrais-je m'inquiéter de disposer du HttpWebResponse ou simplement supposer qu'il sera récupéré? Exemple 'var response = (HttpWebResponse) request.GetResponse(); Renvoyer le fichier (response.GetResponseStream(), "image/JPEG"); ' –

0

Juste pour ajouter à ce Darin has said, il est important de noter ce concept:

public Stream GetDownloadFile(...) 
{ 
    using (var stream = new MemoryStream()) { 
    return stream; 
    } 
} 

public Stream GetDownloadFile(...) 
{ 
    using (var generator = DocumentGenerator.OpenTemplate(path)) 
    { 
    // Document manipulation. 

    return File(generator.GetDocumentStream(), "text/plain", filename); 
    } 
} 

Quelle que soit la façon dont vous utilisez dans votre méthode, le bloc à l'aide assure Cédant est toujours appelée, ce qui est important quand vous considérez utiliser le résultat du bloc using comme une déclaration de retour, cela ne l'empêchera pas d'être éliminé ....