David Shochet
David Shochet

Reputation: 5375

How to get contents of System.Net.Mail.Attachment

I have a System.Net.Mail.Attachment object with some .csv data in it. I need to save the contents of the attachment in a file. I tried this:

        var sb = new StringBuilder();
        sb.AppendLine("Accounts,JOB,Usage Count");


            sb.AppendLine("One,Two,Three");
            sb.AppendLine("One,Two,Three");
            sb.AppendLine("One,Two,Three");

        var stream = new MemoryStream(Encoding.ASCII.GetBytes(sb.ToString()));
        //Add a new attachment to the E-mail message, using the correct MIME type
        var attachment = new Attachment(stream, new ContentType("text/csv"))
        {
            Name = "theAttachment.csv"
        };


            var sr = new StreamWriter(@"C:\Blah\Look.csv");
            sr.WriteLine(attachment.ContentStream.ToString());
            sr.Close();

But the file has only the following: "System.IO.MemoryStream". Could you please tell me how I can get the real data there?

Thanks.

Upvotes: 2

Views: 7390

Answers (2)

Kevin DiTraglia
Kevin DiTraglia

Reputation: 26058

Assuming your stream isn't too big you can just write it all to the file like so:

StreamWriter writer = new StreamWriter(@"C:\Blah\Look.csv"); 
StreamReader reader = new StreamReader(attachment.ContentStream); 
writer.WriteLine(reader.ReadToEnd()); 
writer.Close();

If it is bigger you probably want to chunk the reads up into a loop as to not demolish your RAM (and risk out of memory exceptions).

Upvotes: 0

vcsjones
vcsjones

Reputation: 141638

You can't call ToString on an arbitrary stream. Instead you should use CopyTo:

using (var fs = new FileStream(@"C:\temp\Look.csv", FileMode.Create))
{
    attachment.ContentStream.CopyTo(fs);
}

Use this to replace the last three lines of your example. By default, ToString just returns that name of the type unless the class overrides ToString. ContentStream is just the abstract Stream (at runtime it is a MemoryStream), so there is just the default implementation.

CopyTo is new in .NET Framework 4. If you aren't using the .NET Framework 4, you can mimic it with an extension method:

public static void CopyTo(this Stream fromStream, Stream toStream)
{
    if (fromStream == null)
        throw new ArgumentNullException("fromStream");
    if (toStream == null)
        throw new ArgumentNullException("toStream");

    var bytes = new byte[8092];
    int dataRead;
    while ((dataRead = fromStream.Read(bytes, 0, bytes.Length)) > 0)
        toStream.Write(bytes, 0, dataRead);
}

Credit to Gunnar Peipman for the extension method on his blog.

Upvotes: 6

Related Questions