0

In a Blazor WebAssembly project I'm working on, I am compressing data at a back-end WebAPI server and passing it up to the front-end Blazor server (running Blazor WebAssembly, not "Blazor Server," yay for confusing terminology), to be delivered to the user who then decompresses it. I'm running into the following exception:

System.IO.IOException: Corrupted data ReadInternal at System.IO.Compression.DeflateStreamNative.CheckResult (System.Int32 result, System.String where) <0x34fa860 + 0x000f0> in :0 at System.IO.Compression.DeflateStreamNative.ReadZStream (System.IntPtr buffer, System.Int32 length) <0x34f9c60 + 0x00024> in :0 at System.IO.Compression.DeflateStream.ReadInternal (System.Byte[] array, System.Int32 offset, System.Int32 count) <0x34f9a90 + 0x00066> in :0 at System.IO.Compression.DeflateStream.Read (System.Byte[] array, System.Int32 offset, System.Int32 count) <0x34f96e8 + 0x000cc> in :0 at System.IO.Compression.GZipStream.Read (System.Byte[] array, System.Int32 offset, System.Int32 count) <0x34f33b0 + 0x0001e> in :0 at OptionalyticsFrontend.Shared.Services.Compression.DecompressString (System.Byte[] input) [0x0001b] in C:\Users\codef\source\repos\OptionalyticsFrontend\OptionalyticsFrontend\Shared\Services\Compression.cs:24 at OptionalyticsFrontend.Client.Pages.Application.GetFilteredOptions () [0x00183] in C:\Users\codef\source\repos\OptionalyticsFrontend\OptionalyticsFrontend\Client\Pages\Application.razor:310

I've looked at the specified lines over and over, and looked at Google and Stack Overflow for a while, and can't figure it out. The following are the compression/decompression methods used on both back and front end:

public static string DecompressString(this byte[] input)
{
    var result = new byte[input.Length];
    using (var source = new MemoryStream(input))
    {
        using (var decompressionStream = new GZipStream(source,
            CompressionMode.Decompress))
        {
            decompressionStream.Read(result, 0, input.Length); // <---------- THIS IS THE ERROR LINE
        }
    }
    return Encoding.UTF8.GetString(result);
}

public static byte[] CompressString(this string inputString)
{
    byte[] input = Encoding.UTF8.GetBytes(inputString);
    using (var result = new MemoryStream())
    {
        using (var compressionStream = new GZipStream(result,
            CompressionMode.Compress))
        {
            compressionStream.Write(input, 0, input.Length);
            compressionStream.Flush();

        }
        return result.ToArray();
    }
}

The following line is where the decompression is called, in my Razor component:

var responseString = OptionalyticsFrontend.Shared.Services.Compression.DecompressString(responseBytes);

I have looked at, and tried implementing, the following Stack Overflow answers, and none of them worked, I still get the same exception every time.

GZipStream And DeflateStream will not decompress all bytes

GZipStream does gzipping but ungzipping file end up with "Unexpected end of data"

GZipStream zip file invalid or corrupted

Gzip compression and decompression in C#

What is going on here? I am running the front-end Blazor server as .NET Standard and .NET Core (the actual client and shared codes are .NET Standard, server-side is .NET Core)

EDIT: As Andy's comment asked, I added a new stream and tried copying to the new stream, but this results in the same error.

public static string DecompressString(byte[] input)
{
    var result = new byte[input.Length];
    using (var newStream = new MemoryStream())
    {
        using (var source = new MemoryStream(input))
        {
            using (var decompressionStream = new GZipStream(source,
                CompressionMode.Decompress))
            {
                decompressionStream.CopyTo(newStream);
            }
        }
        newStream.Position = 0;
        return Encoding.UTF8.GetString(newStream.ToArray());
    }
}
Codefun64
  • 593
  • 2
  • 9
  • 18
  • instead of using `decompressionStream.Read`, create a new memory stream and do `decompressionStream.CopyTo(theNewMemoryStream);`, then do `theNewMemoryStream.Position = 0; Encoding.UTF8.GetString(theNewMemoryStream.ToArray());` – Andy Feb 21 '21 at 03:28
  • @Andy Tried it, didn't work. Same exact exception. New code will be added to answer in a second. – Codefun64 Feb 21 '21 at 03:32
  • I tried you code and it worked fine. No idea what's going on with your project. If you do this: `var ret = "hello".CompressString().DecompressString();` i get no errors. It works perfect when you use `CopyTo` code above. – Andy Feb 21 '21 at 03:54
  • @Andy It turns out it's because in one of my files somewhere in all this exchange of data between servers, I used `await response.Content.ReadAsByteArrayAsync()` instead of `await response.Content.ReadAsAsync()`, and this was breaking everything. – Codefun64 Feb 21 '21 at 04:12

1 Answers1

1

The problem, apparently, is that inside of my Application.razor file, I was calling back to my front-end server with await response.Content.ReadAsByteArrayAsync() rather than await response.Content.ReadAsAsync<byte[]>(), and you want the LATTER because the former somehow transforms the data in a way you don't necessarily expect, that, when converted to a UTF8 string, looks remarkably like a Base64 string. Strange behaviors abound.

Codefun64
  • 593
  • 2
  • 9
  • 18