Stream a ZIP and emailing file

Jun 22, 2009 at 5:22 AM

Hi,

Using a c# windows form I would like to convert some text to a stream, encode as HTM then add into a ZIP stream (always 1 HTM file Zipped/protected) and then email out (passing the stream) as parameter to MailMessage. (all without saving to disk)

 

using (MailMessage email = new MailMessage())
{
..... <some code>
Attachment attach = new Attachment(zipFile);
email.Attachments.Add(attach);
}

 

Firstly, I am wondering if this is possible?

 

I have attempted to do this:

 

                MemoryStream ms = new MemoryStream();
                using (ZipFile zip = new ZipFile())
                {
                    zip.AddFileFromString(htm_filename, "", htm_data);
                    zip.Save(ms);
                }
                Console.WriteLine("Output stream Length: " + ms.Length + " CanWrite: " + ms.CanWrite + " Capacity: " + ms.Capacity + " CanRead: " + ms.CanRead);

 

But when using below to read the stream (for testing purposes) :

                MemoryStream os = new MemoryStream();
                using (ZipFile ez = ZipFile.Read(ms))
                {
                    ez.Extract("output.htm");
                }
                Console.WriteLine("Output stream Length: " + os.Length + " CanWrite: " + os.CanWrite + " Capacity: " + os.Capacity + " CanRead: " + os.CanRead);

I get an error with output... (below)

Output stream Length: 130 CanWrite: True Capacity: 256 CanRead: True
Error: Could not read block - no data!  (position 0x00000082)

 

So it appears as if saving the ms stream but not able to read it back... ?

Thank you for any assistance on this.

Coordinator
Jun 22, 2009 at 4:19 PM
Edited Jan 10, 2010 at 2:52 PM

Yes, what you want to do is very possible.

The problem happens because the stream pointer for your MemoryStream ms is at the end of the stream, when you try to read the zip content from it.  To correct this, you need to set the cursor in the MemoryStream back to the beginning, between writing and reading.

        ms.Seek(0, SeekOrigin.Begin);

That worked for me.

EDIT: Just re-read your question.  Let me clarify my answer: the ms.Seek() will work to allow your test case to succeed.  I don't know about the interface for MailMessage() and whether you can create an attachment from a stream.  So I don't know for certain that what you want to do is possible, but I do know that the stream handling necessary on the DotNetZip side is in place to allow what you want.  If you know what I mean.  If MailMessage does allow stream inputs, do the ms.Seek() before providing the MemoryStream to MailMessage or Attachement or whatever.

Ps: in v1.8, the ZipFile.AddFileFromString() method was renamed to ZipFile.AddEntry().

Jun 22, 2009 at 8:25 PM

Yes, your single line was everything I was missing. The stream to email worked as well. Thanks!

Coordinator
Jun 26, 2009 at 4:00 PM

Hey rubberdown, just ouf of curiosity, can you tell me more about the app or system you are building? 

Jun 27, 2009 at 2:11 PM

Sure its for a simple SQL Server CLR that is called. You have some interest?

Coordinator
Jun 27, 2009 at 3:00 PM

yeah, I am always interested to hear where DotNetZip gets used. It started as a little thing and its gotten to be pretty big.  SQL Server CLR, eh?  Sending out emails with zip attachments.b  Anything else you can tell me?  Like I said, just curious.

Jun 27, 2009 at 3:18 PM

Yea definitely big with a lots of possibilities in terms of use. I have a stored proc on SQL Server that runs at intervals during the day (incidentally there are tables being populated) - this stored proc calls my SQL CLR and passes the data from the table which needs to be sent in HTML format to our reader (external user, sensitive data) which is where Dotnetzip comes in. It is not time critical data, same day (of INSERT and email send) is sufficient. Which is in a nutshell :)

I am unsure if the .NET packaging or other inbuilt classes would allow this but am glad I came across Dotnetzip!