Avoid disk usage as an intermediate step for Zip Compression in C#

104 views Asked by At

The official C# documentation states, that ZipFile.CreateFromDirectory() creates a zipfile on the disk, as an intermediate step. However I need my system to run on devices where disk space is critical. Can I somehow just create the Zipfile in memory?

2

There are 2 answers

0
AudioBubble On

.NET 8 adds exactly what you are looking or!! It adds new overloads as documented in Stream-based ZipFile methods:

.NET 8 includes new overloads of ZipFile.CreateFromDirectory that allow you to collect all the files included in a directory and zip them, then store the resulting zip file into the provided stream. Similarly, new ZipFile.ExtractToDirectory overloads let you provide a stream containing a zipped file and extract its contents into the filesystem. These are the new overloads:

namespace System.IO.Compression;

public static partial class ZipFile
{
    public static void CreateFromDirectory(string sourceDirectoryName, Stream destination);
    public static void CreateFromDirectory(string sourceDirectoryName, Stream destination, CompressionLevel compressionLevel, bool includeBaseDirectory);
    public static void CreateFromDirectory(string sourceDirectoryName, Stream destination, CompressionLevel compressionLevel, bool includeBaseDirectory, Encoding? entryNameEncoding);

    public static void ExtractToDirectory(Stream source, string destinationDirectoryName) { }
    public static void ExtractToDirectory(Stream source, string destinationDirectoryName, bool overwriteFiles) { }
    public static void ExtractToDirectory(Stream source, string destinationDirectoryName, Encoding? entryNameEncoding) { }
    public static void ExtractToDirectory(Stream source, string destinationDirectoryName, Encoding? entryNameEncoding, bool overwriteFiles) { }
}
0
Etienne de Martel On

While .NET 8 adds ZipFile.CreateFromDirectory overloads that allow writing to a stream directly, you don't have to wait for that to come out to do that.

Instead, you can simply create a ZipArchive with your stream and a ZipArchiveMode of Create, and then add entries to it:

public static void CreateZipArchive(string sourceDirectory, Stream destination)
{
    using var archive = new ZipArchive(destination, ZipArchiveMode.Create, true);
    foreach (var file in Directory.EnumerateFiles(sourceDirectory, "*", SearchOption.AllDirectories))
    {
        var entryName = Path.GetRelativePath(sourceDirectory, file).Replace(Path.DirectorySeparatorChar, '/');
        archive.CreateEntryFromFile(file, entryName);
    }
}

Use a MemoryStream to write to memory.