Copying Stream from XmlTextWriter to a FileStream
I have an HTTP Handler that is binding an XmlTextWriter
instance to Response.Output
like so...
Sub GenerateXml(ByRef Response As HttpWebResponse)
Using Writer As New XmlTextWriter(Response.Output)
' Build XML
End Using
End Sub
And now I also want the same XML to be saved to the local hard drive (in addition to being streamed to the response). How can I do it?
Things I have tried
1) The obvious, copying the Response.OutputStream to a new FileStream...
Sub GenerateXml(ByRef Response As HttpWebResponse) Using Writer As New XmlTextWriter(Response.Output) Build XML Here End Using // Also tried this inside the Using, with and without .Flush() CopyStream(Response.OutputStream, File.Create("C:\test.xml")) End Sub Sub CopyStream(ByRef Input As Stream, ByRef Output As Stream) Dim Buffer(1024) As Byte Dim Read As Integer Using Input Using Output While (Read = Input.Read(Buffer, 0, Buffer.Length)) > 0 Output.Write(Buffer, 0, Read) End While End Using End Using End Sub
I get errors like "Method not supported" and "Nul开发者_运维问答lReference"
2) Using a Memory Stream and then copying it...
Using Memory As New MemoryStream()
Using Writer As New XmlTextWriter(Memory, Encoding.UTF8)
Build XML Here
End Using
// Tried outside of the Using, with and without Flush()
CopyStream(Memory, Response.OutputStream)
CopyStream(Memory, File.Create("C:\test.xml"))
End Using
I get errors like "Cannot access a closed Stream."
Why is something so simple such a PITA?!
You can't wire up Response.OutputStream
in that manner. However, you could do one of two things:
Create a method that calls
Stream.Write
for both your test file andResponse.OutputStream
.using (var writerResponse = new XmlTextWriter(Response.OutputStream)) using (var writerFile = new XmlTextWriter(File.Create(@"c:\test.xml")) { StartElement(writerResponse, writerFile, @"test"); }
Create a wrapper class which encapsulates two streams to be written to and provides all of the stream methods you require (
Write
etc).public class DualStream : Stream { public DualStream(Stream first, Stream second) { } public override bool CanRead { get { return false; } } public override bool CanWrite { get { return true; } } public override void Write(byte[] buffer, int offset, int count) { this.first.Write(buffer, offset, count); this.second.Write(buffer, offset, count); } } // ... using (var writerFile = new XmlTextWriter(File.Create(@"c:\test.xml"))) using (var writer = new XmlTextWriter( new DualStream(Response.OutputStream, writerFile)), null)) { // use writer }
You need to reset the memorystream position to 0.
i.e.:
Memory.Position = 0
Have you tried the save method?
http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.save%28VS.71%29.aspx
I don't know if you will be able to use it in your context.
I found this EchoStream class on codeproject by googling for .net stream tee
(tee being the unix-y word for what you want).
精彩评论