简体   繁体   English

在ASP.NET中实现文件下载时如何处理文件流?

[英]How do I dispose my filestream when implementing a file download in ASP.NET?

I have a class DocumentGenerator which wraps a MemoryStream . 我有一个DocumentGenerator类,它包装了一个MemoryStream So I have implemented IDisposable on the class. 所以我在课堂上实现了IDisposable

I can't see how/where I can possibly dispose it though. 我看不出如何/在哪里可以处理它。

This is my current code, which performs a file download in MVC: 这是我当前的代码,它在MVC中执行文件下载:

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

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

This errors as the stream is closed/disposed before the controller has finished with it. 在控制器完成之前关闭/处理流时出现此错误。 How can I make sure my resources are properly disposed in this situation? 在这种情况下,如何确保我的资源得到妥善处理?

EDIT: My implementation of IDisposable at the moment just disposes the MemoryStream . 编辑:我目前的IDisposable实现只是处理MemoryStream I know it's not a proper implementation, I just used it as a test. 我知道这不是一个正确的实现,我只是用它作为测试。 Is there something different I could do here to make it work? 有什么不同我可以在这里做它的工作吗?

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

You don't need to dispose the stream. 您不需要处理流。 It will be disposed by the FileStreamResult.WriteFile method. 它将由FileStreamResult.WriteFile方法处理。 Code excerpt from this class: 此类的代码摘录:

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

Notice the using . 注意using When you call File(dg.GetDocumentStream(), "text/plain", filename) from your controller this invokes the constructor which stores the stream into a public property which is disposed during the rendering. 当您从控制器调用File(dg.GetDocumentStream(), "text/plain", filename) ,它会调用构造函数,该构造函数将流存储到在呈现期间处置的公共属性中。

Conclusion: you don't need to worry about disposing the stream obtain with dg.GetDocumentStream() . 结论:您不必担心使用dg.GetDocumentStream()处理获取的流。

Just to add to what Darin has said , it's important to note this 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);
  }
}

Regardless of how you are using it in your method, the using block ensures that Dispose is always called, this is important when you consider to use the result of the using block as a return statement, it won't stop it from being disposed.... 无论您在方法中如何使用它,using块都确保始终调用Dispose,这在您考虑使用using块的结果作为return语句时很重要,它不会阻止它被处置。 ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM