views:

144

answers:

3

Consider the following code:

Stream stream = GetStreamFromSomewhere(); 
XmlDictionaryReader mtomReader =XmlDictionaryReader.CreateMtomReader
(
 stream,
 Encoding.UTF8,
 XmlDictionaryReaderQuoatas.Max
);

/// ...

/// is there best way to read binary data from mtomReader's element??
string elementString = mtomReader.XmlReader.ReadElementString();
byte[] elementBytes = Covert.FromBase64String(elementString);
Stream elementFileStream = new FileStream(tempFileLocation);
elementFileStream.Write(elementBytes,0,elementBytes.Length);
elementFileStream.Close();

/// ...

mtomReader.Close();

The problem is that the size of the binary attachment supposed to be over 100Mb sometimes. Is there a way to read element's binary attachment block by block and then write it to the temporary file stream so i can escape from allocating memory for the hole stuff?

The second - even more specific issue - does mtomReader create any internal cache of the mime binary attachment before i read element's content, i.e. allocate memory for binary data? Or does it read bytes from the input stream directly?

A: 

For an attachment of that size it would be better to use streaming.

Streamed transfers can improve the scalability of a service by eliminating the requirement for large memory buffers. Whether changing the transfer mode improves scalability depends on the size of the messages being transferred. Large message sizes favor using streamed transfers.

See: http://msdn.microsoft.com/en-us/library/ms731913.aspx

Shiraz Bhaiji
Thanks. But that doesn't asnwer my questions either. I'm working with XmlMtomReader, not WCF services.
sh0gged
A: 

To begin with, your code should be more like this:

using (Stream stream = GetStreamFromSomewhere())
{
    using (
        XmlDictionaryReader mtomReader = XmlDictionaryReader.CreateMtomReader(
            stream, Encoding.UTF8, XmlDictionaryReaderQuotas.Max))
    {
        string elementString = mtomReader.ReadElementString();
        byte[] elementBytes = Convert.FromBase64String(elementString);
        using (
            Stream elementFileStream =
                new FileStream(tempFileLocation, FileMode.Create))
        {
            elementFileStream.Write(
                elementBytes, 0, elementBytes.Length);
        }

        /// ...

        mtomReader.Close();
    }
}

Without the using blocks, you're at risk of resource leaks.

John Saunders
That's right. But this doesn't solve my problem anyway. :(
sh0gged
I had hoped the answer would be obvious, but it wasn't. I thnink maybe using the `ReadSubTree` method along with reading the content in chunks might help, but I don't know for sure
John Saunders
+1  A: 

For those who may be interested in the solution:

using (Stream stream = GetStreamFromSomewhere())
{
  using (
    XmlDictionaryReader mtomReader = XmlDictionaryReader.CreateMtomReader(
        stream, Encoding.UTF8, XmlDictionaryReaderQuotas.Max))
 {
    string elementString = mtomReader.ReadElementString();
    byte[] buffer = new byte[1024];
    using (
        Stream elementFileStream =
            new FileStream(tempFileLocation, FileMode.Create))
    {
        while(mtomReader.XmlReader.ReadElementContentAsBase64(buffer,0,buffer.Length)
        {
          elementFileStream.Write(buffer, 0, buffer.Length);
        }
    }

    /// ...

    mtomReader.Close();
 }
}

ReadElementContentAsBase64(...) helps read binary parts block by block. The second issue of my post was covered perfectly here: http://stackoverflow.com/questions/1503711/does-xmlmtomreader-cache-binary-data-from-the-input-stream-internally

sh0gged