2010-06-21 6 views
19

Ho una classe DocumentGenerator che include uno MemoryStream. Quindi ho implementato IDisposable sulla classe.Come posso disporre del filestream durante l'implementazione di un download di file in ASP.NET?

Non riesco a vedere come/dove posso possibilmente disporlo però.

Questo è il mio codice corrente, che esegue un download di file in MVC:

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

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

Questo errori come il flusso è chiuso/disposti prima che il controllore ha finito con esso. Come posso assicurarmi che le mie risorse siano disposte correttamente in questa situazione?

MODIFICA: La mia implementazione di IDisposable al momento dispone solo dello MemoryStream. So che non è una corretta implementazione, l'ho solo usato come test. C'è qualcosa di diverso che potrei fare qui per farlo funzionare?

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

Puoi mostrarci l'implementazione di IDisposable, per favore? – DHN

+0

È '_ms' lo stesso che si ottiene dopo aver chiamato' GetDocumentStream'? –

+0

@ Jordão: sì, è corretto, quindi il problema. – fearofawhackplanet

risposta

29

Non è necessario smaltire il flusso. Sarà eliminato dal metodo FileStreamResult.WriteFile. Codice estratto da questa 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); 
     } 
    } 
} 

Avviso del using. Quando si chiama File(dg.GetDocumentStream(), "text/plain", filename) dal controller, viene richiamato il costruttore che memorizza il flusso in una proprietà pubblica che viene eliminata durante il rendering.

Conclusione: non è necessario preoccuparsi di smaltire lo stream ottenere con dg.GetDocumentStream().

+1

Che dire se il flusso proviene da un altro oggetto usa e getta come HttpWebResponse? Dovrei preoccuparmi di smaltire HttpWebResponse o semplicemente supporre che otterrà la raccolta dei dati inutili? Esempio 'var response = (HttpWebResponse) request.GetResponse(); file di ritorno (response.GetResponseStream(), "image/JPEG"); ' –

0

Giusto per aggiungere a quanto Darin has said, è importante notare che questo concetto:

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); 
    } 
} 

Indipendentemente da come lo si utilizza nel metodo, il blocco utilizzando assicura che Dispose viene sempre chiamato, questo è importante quando si considera di utilizzare il risultato del blocco using come dichiarazione di ritorno, non si fermerà dall'eliminazione ....

Problemi correlati