Dayan
Dayan

Reputation: 751

How to compress multiple files in zip file

I'm trying to compress two text files to a zip file. This is how my public method looks like:

public ActionResult Index()
{

    byte[] file1 = System.IO.File.ReadAllBytes(@"C:\file1.txt");
    byte[] file2 = System.IO.File.ReadAllBytes(@"C:\file2.txt");
    Dictionary<string, byte[]> fileList = new Dictionary<string, byte[]>();
    fileList.Add("file1.txt", file1);
    fileList.Add("file2.txt", file2);
    CompressToZip("zip.zip", fileList);

    return View();
}

This is how my compress method looks like:

private void CompressToZip(string fileName, Dictionary<string, byte[]> fileList)
{
    using (var memoryStream = new MemoryStream())
    {
        foreach (var file in fileList)
        {
            using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
            {
                var demoFile = archive.CreateEntry(file.Key);

                using (var entryStream = demoFile.Open())
                using (var b = new BinaryWriter(entryStream))
                {
                    b.Write(file.Value);
                }
            }
        }

        using (var fileStream = new FileStream(fileName, FileMode.Create))
        {
            memoryStream.Seek(0, SeekOrigin.Begin);
            memoryStream.CopyTo(fileStream);
        }
    }

}

In this approach, the zip folder is perfectly created. However the issue is I'm getting only one file inside the zip folder (Just the second file will be created inside the zip folder). There are no errors found.

Question: How to compress both text files into the zip folder?

Thank you in advanced!

Upvotes: 12

Views: 20788

Answers (3)

user2629005
user2629005

Reputation: 21

string startPath = @"c:\example\start";
string zipPath = @"c:\example\result.zip";

ZipFile.CreateFromDirectory(startPath, zipPath);

Upvotes: 0

Phil Ross
Phil Ross

Reputation: 26120

Your code is actually saving two separate zip archives to the zip.zip file (a new ZipArchive is created for each file to be compressed). The first zip archive contains only file1.txt, the second only file2.txt. When you open zip.zip in Windows Explorer, it shows just the contents of the second zip archive.

To create a single zip archive containing both files, just move the creation of the ZipArchive outside of your fileList loop:

using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
    foreach (var file in fileList)
    {                    
        var demoFile = archive.CreateEntry(file.Key);

        using (var entryStream = demoFile.Open())
        using (var b = new BinaryWriter(entryStream))
        {
            b.Write(file.Value);
        }
    }
}

Upvotes: 15

Geoff James
Geoff James

Reputation: 3180

At first glance, I would suggest that your foreach statement around the using var (archive = new ZipArchive...) is the wrong way round.

This way you are creating a new ZipArchive each time you iterate the foreach loop.

Surely you want to create the ZipArchive and loop through the foreach inside of that?

Like this:

private void CompressToZip(string fileName, Dictionary<string, byte[]> fileList)
{
    using (var memoryStream = new MemoryStream())
    {
        using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
        {
            foreach (var file in fileList)
            {   
                var demoFile = archive.CreateEntry(file.Key);

                using (var entryStream = demoFile.Open())
                using (var b = new BinaryWriter(entryStream))
                {
                    b.Write(file.Value);
                }
            }
        }

        using (var fileStream = new FileStream(fileName, FileMode.Create))
        {
            memoryStream.Seek(0, SeekOrigin.Begin);
            memoryStream.CopyTo(fileStream);
        }
    }
}

Hope this helps!

Upvotes: 8

Related Questions