我真的是溪流的新手,所以我真的不知道我在这里做什么。 :)
我有一个包含XML的XElement
。我希望它将它作为文件返回给用户。
XElement xml = IndicesXMLGenerator.XML();
//Code for creating a memorystream for returning to browser as file
MemoryStream stream = new MemoryStream();
XmlTextWriter writer = new XmlTextWriter(stream, System.Text.Encoding.Unicode);
xml.Save(writer);
writer.Close();
//Code for direct saving to harddisk
FileStream filestream = new FileStream(@"D:\indices.xml", FileMode.Create);
XmlTextWriter writer2 = new XmlTextWriter(filestream, System.Text.Encoding.Unicode);
xml.Save(writer2);
writer2.Close();
filestream.Close();
//Return memorystream as fileresult
return base.File(new MemoryStream(stream.GetBuffer()), "text/xml", "AlleIndices.xml");
}
当我打开从浏览器中获取的文件时,它完全被破坏了。
喜欢:�< ? X M L
当我将代码中的编码更改为UTF8
时,它会给我一个看似正常的文档,但最后我会收到很多0x0
个字符,导致文档无效。
奇怪的是,我从代码中直接保存到硬盘的XML文件是:
0x0
字符那么,这里发生了什么?为什么我不能轻松地将我的XElement作为文件流式传输到浏览器?
答案 0 :(得分:2)
调用GetBuffer
将返回流的内部缓冲区,该缓冲区将大于实际数据。 (如果你在流中写了更多内容)
您需要将GetBuffer
的调用替换为ToArray()
,这会将缓冲区的已用部分复制到新数组中。
但是,执行此操作的最佳方法是返回原始的MemoryStream,但首先将Position
属性设置为0,如下所示:
stream.Position = 0;
return File(stream, "text/xml", "AlleIndices.xml");
答案 1 :(得分:1)
您无需创建新的 MemoryStream
,只需重复使用(您只需要Seek
到流的开头)
XML看起来很糟糕,因为浏览器不知道它被编码为Unicode。您需要在响应中添加 Content-Encoding 标头以指定编码
答案 2 :(得分:0)
MemoryStream
实现了一种数组加倍技术,以便在添加字节时可以有效地调整大小。这意味着缓冲区通常大于实际数据。
有一些解决方案:
ToArray
代替GetBuffer
。MemoryStream
构造函数。例如:
new MemoryStream(stream.GetBuffer(), 0, (int)stream.Length)
答案 3 :(得分:0)
如果您编写如下代码,那么从长远来看,您将会更加快乐:
XElement xml = IndicesXMLGenerator.XML();
using (MemoryStream ms = new MemoryStream())
using (XmlWriter xw = XmlWriter.Create(ms))
{
xml.Save(xw);
}
XmlWriter.Create
,而不是XmlTextWriter
,并使用XmlWriterSettings
来控制编码和格式。using
块而非显式调用Flush
和Close
- 这样您就不必明确调用它们。那就是说,这实际上不是你的问题,正如所指出的那样是使用GetBuffer
代替ToArray
。但正如我所说,从长远来看,你会更幸福。