我试图提示可下载的文本文件(.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);
}
答案 0 :(得分:46)
这是正确的,当您将流包装在另一个流中时,在其中任何一个上调用.Close()
或.Dispose()
将处理整个流。在这种情况下,将MemoryStream
包裹在StreamWriter
中意味着当using
语句完成后,StreamWriter
和MemoryStream
都会被处理掉。
我的猜测是,因为您返回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
。