Title image of How to gzip compress and decompress in C#

How to gzip compress and decompress in C#

17 June 2023

·
C#

What is Gzip?

Gzip is a common file format used across the web for compressing website assets such as CSS, Javascript and JSON. The assets become smaller and quicker to download, making the website load faster. Using Gzip is very convenient with modern browsers. Browsers will automatically decompress any file with the Content-Encoding header set to “Gzip”. So there’s literally no change in how these assets are used in the front end. All the magic happens in the back end.

An example of the impact of Gzip is how I used it on my side project https://housepricewatch.com. The website shows house price trends broken down by area for the whole of the UK. The house price data for an area is stored in a single JSON file. The file can get quite large so Gzip is needed to keep the size down and the website fast.

The house prices data for the Newport region uncompressed is 286KB. After compressing it with Gzip the data is only 63KB…. that’s 4.5 times smaller.

Compression power of Gzip turning a 286KB json file into just 65KB

Asp.Net Core

Using Gzip is super easy if you’re serving your assets from Asp.Net Core. Microsoft has provided response compression middleware to automatically compress responses.

Enable Gzip by configuring response compression with the Gzip provider:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddResponseCompression(options =>
{
    options.EnableForHttps = true;
    options.Providers.Add<BrotliCompressionProvider>();
    options.Providers.Add<GzipCompressionProvider>();
});

var app = builder.Build();

app.UseResponseCompression();

app.MapGet("/", () => "Hello World!");

app.Run();

Raw C#

.Net has everything needed for Gzip inside the System.IO.Compression namespace.

Compressing

To Gzip compress we need to create a Gzip stream with an outStream, write the data into the Gzip stream and then read the compressed data from the outStream.

using System.IO.Compression;

var data = File.ReadAllBytes("C:/Users/Liam/Downloads/Newport.json");
byte[] compressedData;

using (var outStream = new MemoryStream())
{
    using (var compressor = new GZipStream(outStream, CompressionLevel.Optimal, leaveOpen: true))
    {
        await compressor.WriteAsync(data);
    }

    outStream.Seek(0, SeekOrigin.Begin);

    compressedData = outStream.ToArray();
}

File.WriteAllBytes("C:/Users/Liam/Downloads/Newport-Compressed.json", compressedData);

Decompressing

Decompressing requires creating the GzipStream with an inStream containing the compressed data and setting the compression mode to decompress. The decompressed data can then be read from the GzipStream into another outStream.

using System.IO.Compression;

using (var inStream = File.OpenRead("C:/Users/Liam/Downloads/Newport-Compressed.json"))
{
    using (var decompressor = new GZipStream(inStream, CompressionMode.Decompress, leaveOpen: true))
    {
        using (var outStream = new MemoryStream())
        {
            byte[] buffer = new byte[1024];
            int nRead;
            while ((nRead = decompressor.Read(buffer, 0, buffer.Length)) > 0)
            {
                outStream.Write(buffer, 0, nRead);
            }

            outStream.Seek(0, SeekOrigin.Begin);

            File.WriteAllBytes("C:/Users/Liam/Downloads/Newport-Decompressed.json", outStream.ToArray());
        }
    }
}

Uploading to Azure Blob Storage

Some bonus code for anyone uploading the Gzipped data to Azure blob storage. It’s important to set the ContentEncoding blob Http header so that blobs will get automatically decompressed by browsers.

var serviceClient = new BlobServiceClient("");
var containerClient = serviceClient.GetBlobContainerClient("");

await containerClient.GetBlobClient("gzipped-blob").UploadAsync(
    outStream,
    new BlobUploadOptions
    {
        HttpHeaders = new BlobHttpHeaders
        {
            ContentType = "application/json",
            ContentEncoding = "gzip"
        }
    });