Search code examples
c#dotnetzip

How to attach files to dotnet zip library c#


I am using dotnet zip library to create zip file. My files are saved into a database and I am reading each row and load file data into memory from the database and save the memory stream to zip file. my below code works fine.

using System.IO;
using Ionic.Zip;

private void button2_Click(object sender, EventArgs e)
        {
            using (SqlConnection sqlConn = new SqlConnection(@"Data Source=BBATRIDIP\SQLSERVER2008R2;Initial Catalog=test;Integrated Security=True"))
            {
                string query = String.Format(@"SELECT Name, ContentType, Data FROM [TestTable]");
                SqlCommand cmd = new SqlCommand(query, sqlConn);
                cmd.Connection.Open();

                System.IO.MemoryStream memStream = null;
                ZipFile zip = new ZipFile();
                zip.MaxOutputSegmentSize = 1024 * 1024; // 1MB each segment size would be
                // the above line would split zip file into multiple files and each file
                //size would be 1MB
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        byte[] data = (byte[])reader["Data"];
                        memStream = new System.IO.MemoryStream(data);
                        string strFile = reader["Name"].ToString() + "\\" + reader["ContentType"].ToString();
                        ZipEntry ze = zip.AddEntry(strFile, memStream);
                        int xx = 0;
                    }
                }
                zip.Save(@"e:\MyCustomZip.zip");

                memStream.Dispose();
                MessageBox.Show("Job Done");
                // here u can save the zip in memory stream also there is a overload insteaa of saving in HD
            }
        }

but if i change a bit into the code then corrupted zip file is creating. if i change this line zip.Save(@"e:\MyCustomZip.zip"); then problem occur.

    using (SqlConnection sqlConn = new SqlConnection(@"Data Source=BBATRIDIP\SQLSERVER2008R2;Initial Catalog=test;Integrated Security=True"))
    {
        string query = String.Format(@"SELECT Name, ContentType, Data FROM [TestTable]");
        SqlCommand cmd = new SqlCommand(query, sqlConn);
        cmd.Connection.Open();

        System.IO.MemoryStream memStream = null;
        ZipFile zip = new ZipFile();
        zip.MaxOutputSegmentSize = 1024 * 1024; // 1MB each segment size would be
        // the above line would split zip file into multiple files and each file
        //size would be 1MB
        zip.Save(@"e:\MyCustomZip.zip");
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                byte[] data = (byte[])reader["Data"];
                memStream = new System.IO.MemoryStream(data);
                string strFile = reader["Name"].ToString() + "\\" + reader["ContentType"].ToString();
                ZipEntry ze = zip.AddEntry(strFile, memStream);
                int xx = 0;
            }
        }


        memStream.Dispose();
        MessageBox.Show("Job Done");
        // here u can save the zip in memory stream also there is a overload insteaa of saving in HD
    }

I want to create zip with zero kb initially and when I will add stream to zip in loop then zip file size will increase gradually. if you see my above code where I try to do that but I got no success. what am I doing wrong in the code?

Another issue

dotnet zip compression ratio not good. i zip a 152 KB doc file with dotnet zip and when zip was created then i was zip file size was 136KB. is there any tweak exist which create small size zip file. share the knowledge. thanks


Solution

  • So, looking at the documentation for ZipFile.Save, we see the following:

    Use this when creating a new zip file, or when updating a zip archive.

    So, it seems that you need to call this repeatedly to get the "update" behaviour you are looking for. As such just need to move your Save into the loop:

    //...
    ZipFile zip = new ZipFile();
    zip.MaxOutputSegmentSize = 1024 * 1024; 
    
    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
            byte[] data = (byte[])reader["Data"];
            memStream = new System.IO.MemoryStream(data);
            string strFile = 
                reader["Name"].ToString() + "\\" + reader["ContentType"].ToString();
            ZipEntry ze = zip.AddEntry(strFile, memStream);
            zip.Save(@"e:\MyCustomZip.zip");
        }
    }
    

    With regards to your second question (never a good idea on SO, try to stick to one problem per question):

    Without knowing what you are compressing, it's very difficult to speculate about what kind of compression ratio you might achieve. If the data is already compressed (e.g. compressed image/video such as jpeg/h264), zipping isn't going to give you any gains whatsoever. Your only hint about the nature of the content is that it is a "doc". If you're talking about a modern Word document (docx), this is already a zip compressed folder structure. Gains will be minimal. If it's another kind of doc, perhaps it contains embedded (compressed) media? This will also be relatively incompressible.