在asp.net MVC 3中创建可下载文本文件时,无法访问已关闭的流

本文关键字:访问 文件 MVC net asp 创建 文本 下载 | 更新日期: 2023-09-27 18:06:17

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

无法访问已关闭的流。

我在这里看到了类似的问题:无法访问已关闭的流但它并不是很有用。

下面是我的代码:
    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);
    }

UPDATE (working copy):

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

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

在asp.net MVC 3中创建可下载文本文件时,无法访问已关闭的流

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

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

由于流是前向访问,所以你需要看到流回到开头,以允许数据被读回。

stream.Seek(0, SeekOrigin.Begin);

只是删除using语句-你正在传递处置对象引用到File方法,你这就是为什么你得到异常的原因。从MSDN,

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

我相信File将在使用后自行处理流(未通过查看源代码进行验证)。

更新:

writer.Flush(); before return语句可以帮助您

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

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

有相同的东西。

我知道这是一个古老的帖子,只是希望能帮助其他人有同样的问题。

将动作上的FileStreamResult类型替换为FileResult