在ASP MVC 3中创建可下载的文本文件时无法访问封闭的流

时间:2011-08-22 19:34:00

标签: c# asp.net-mvc-3 asp.net-mvc

我试图提示可下载的文本文件(.txt),但是我收到了这个错误:

  

无法访问已关闭的流。

我在这里看过类似的问题: Cannot Access Closed Stream 但它不是很有用。

这是我的代码:

    private FileStreamResult Export()
    {
        string name = "filename.txt";

        MemoryStream stream = new MemoryStream();
        using (StreamWriter writer = new StreamWriter(stream))
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("A text...");
            writer.WriteLine(sb.ToString());
        }

        return File(stream, "text/plain", name);
    }

更新(工作副本):

这给了我一个空白文本文件。

private FileResult Export()
{
    string name = "filename.txt";

    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);

    StringBuilder sb = new StringBuilder();
    sb.Append("A text...");
    writer.WriteLine(sb.ToString());

    writer.Flush();
    stream.Seek(0, SeekOrigin.Begin);

    return File(stream, "text/plain", name);
}

4 个答案:

答案 0 :(得分:46)

这是正确的,当您将流包装在另一个流中时,在其中任何一个上调用.Close().Dispose()将处理整个流。在这种情况下,将MemoryStream包裹在StreamWriter中意味着当using语句完成后,StreamWriterMemoryStream都会被处理掉。

我的猜测是,因为您返回FileStreamResult,封装File将在不再使用流后为您关闭流。在这种情况下,您不希望使用using语句,并希望在返回时保持流打开。

<强>更新

由于流是前向访问,因此您需要将流返回到开头以允许读取数据。

stream.Seek(0, SeekOrigin.Begin);

答案 1 :(得分:7)

只需删除using语句 - 您正在将已处置对象引用传递给File方法,这就是您获得异常的原因。来自MSDN

  

StreamWriter对象在提供的Stream对象上调用Dispose   调用StreamWriter.Dispose时。

我相信File会在使用后自行配置流(未通过查看源代码验证)。

<强>更新

在return语句之前

writer.Flush();应该帮助你

答案 2 :(得分:3)

在FileStreamResult中使用它之前,你必须将memorystream的位置设置为0,否则它将从当前位置读取(IE是流的末尾)。

stream.Position = 0;
return File(stream, "text/plain", name);

刚才有同样的事情。

我知道这个话题很古老,只是希望能帮助其他人解决同样的问题。

答案 3 :(得分:1)

将您的操作上的FileStreamResult类型替换为FileResult