Search code examples
c#.netzipdeflatedeflatestream

Create in memory zip from a file


Is DeflateStream supposed to create archived stream that can be stored as standard .zip archive?

I'm trying to create in-memory zip (to be sent remotely) from a local file. I used a DeflateStream to get a compressed byte array from the file on local disk:

public static byte[] ZipFile(string csvFullPath)
    {
        using (FileStream csvStream = File.Open(csvFullPath, FileMode.Open, FileAccess.Read))
        {
            using (MemoryStream compressStream = new MemoryStream())
            {
                using (DeflateStream deflateStream = new DeflateStream(compressStream, CompressionLevel.Optimal))
                {
                    csvStream.CopyTo(deflateStream);
                    deflateStream.Close();
                    return compressStream.ToArray();
                }
            }
        }
    }

This works great. However when I dump the resulting bytes to a zip file:

byte[] zippedBytes = ZipFile(FileName);
File.WriteAllBytes("Sample.zip", zippedBytes);

I cannot open the resulting .zip archive with windows build-in .zip functionality (or with any other 3rd party archive tool).

An alternative I'm planning now is using ZipArchive - however that would require creating temporary files on disk (first copy the file into separate directory, then zip it, then read it into byte array and then delete it)


Solution

  • You can use this nice library https://dotnetzip.codeplex.com/

    or you can use ZipArchive and it works with MemoryStream pretty good:

    public static byte[] ZipFile(string csvFullPath)
    {
        using (FileStream csvStream = File.Open(csvFullPath, FileMode.Open, FileAccess.Read))
        {
            using (MemoryStream zipToCreate = new MemoryStream())
            {
                using (ZipArchive archive = new ZipArchive(zipToCreate, ZipArchiveMode.Create, true))
                {
                    ZipArchiveEntry fileEntry = archive.CreateEntry(Path.GetFileName(csvFullPath));
                    using (var entryStream = fileEntry.Open())
                    {
                        csvStream.CopyTo(entryStream);
                    }
                }
    
                return zipToCreate.ToArray();
            }
        }
    }