1

i am developing an application where i compress large JSON data using pako.gzip and then use the btoa function to make it base64string in order to post the data to the server. In the javascript i wrote:

    var data = JSON.stringify(JSONData);
    var ZippedData = pako.gzip(data, { to: 'string' });
    var base64String = btoa(ZippedData);
    /* post to server*/
    $http.post("URL?base64StringParam=" + base64String").then(function (response) {
        //do stuff
    });

the problem is that i need to decompress the data again in C# code after posting in order to do other workings on it. In the C# code i wrote:

    byte[] data = Convert.FromBase64String(base64StringParam);
            string decodedString = System.Text.ASCIIEncoding.ASCII.GetString(data);
            Encoding enc = Encoding.Unicode;
            MemoryStream stream = new MemoryStream(enc.GetBytes(decodedString));
            GZipStream decompress = new GZipStream(stream, CompressionMode.Decompress);
            string plainDef = "";

and i get the error here

    using (var sr = new StreamReader(decompress))
            {
                plainDef = sr.ReadToEnd();
            }

Found invalid data while decoding.

any help to decompress the data back in C# will be appreciated

EDIT:to sum up what needed to be done javascript does the following:

Plain text >> to >> gzip bytes >> to >> base64 string

i need C# to do the reverse:

Base64 >> to >> unzip bytes >> to >> plain text

  • did you ever figure this out? – Rafi Dec 06 '19 at 07:22
  • no, i used another approach to compress to LZString in Javascript and decompress in C# – Abd-elhameed Quraim Dec 16 '19 at 10:54
  • well I figured it out for my needs. Posting below as an answer to your question – Rafi Dec 18 '19 at 06:50
  • nice work, but as far as i know LZString is more powerfull than GZip,Please check this link on how to use LZString in C# and javascript and Visa-versa. https://devananddhage.wordpress.com/2015/04/30/compress-json-at-client-side-and-decopress-using-c-gzip/?unapproved=87&moderation-hash=cac9947136bd78ebe138beab45e564ea#comment-87 – Abd-elhameed Quraim Dec 20 '19 at 18:20
  • Thanks. Do you have stats about how much it compressed? I know it depends on the input data. For me gzip compressed it 30%. LZString does more? – Rafi Dec 23 '19 at 13:17
  • it depends on the data, for me i compress large amounts of data; files and JSON data and it may contain Unicode characters, so it is hard to tell really, but this method works on both sides server and client code without any other functions and i prefer it and works well for my work. – Abd-elhameed Quraim Dec 23 '19 at 16:23

2 Answers2

0

Assuming the following js:

dataToCommitString = btoa(pako.gzip(dataToCommitString, { to: "string" }));

This is the correct c# code to compress/decompress with GZip: Taken from https://stackoverflow.com/a/7343623/679334

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace YourNamespace
{

    public class GZipCompressor : ICompressor
    {
        private static void CopyTo(Stream src, Stream dest)
        {
            byte[] bytes = new byte[4096];

            int cnt;

            while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0)
            {
                dest.Write(bytes, 0, cnt);
            }
        }

        public byte[] Zip(string str)
        {
            var bytes = Encoding.UTF8.GetBytes(str);

            using (var msi = new MemoryStream(bytes))
            using (var mso = new MemoryStream())
            {
                using (var gs = new GZipStream(mso, CompressionMode.Compress))
                {
                    //msi.CopyTo(gs);
                    CopyTo(msi, gs);
                }

                return mso.ToArray();
            }
        }

        public string Unzip(byte[] bytes)
        {
            using (var msi = new MemoryStream(bytes))
            using (var mso = new MemoryStream())
            {
                using (var gs = new GZipStream(msi, CompressionMode.Decompress))
                {
                    //gs.CopyTo(mso);
                    CopyTo(gs, mso);
                }

                return Encoding.UTF8.GetString(mso.ToArray());
            }
        }
    }
}

Calling it as follows:

value = _compressor.Unzip(Convert.FromBase64CharArray(value.ToCharArray(), 0, value.Length));
Rafi
  • 2,433
  • 1
  • 25
  • 33
0

In client use:

let output = pako.gzip(JSON.stringify(obj));

send as: 'Content-Type': 'application/octet-stream'

=====================

then in C#:

[HttpPost]
[Route("ReceiveCtImage")]
public int ReceiveCtImage([FromBody] byte[] data)
{
    var json = Decompress(data);
    return 1;     
}

public static string Decompress(byte[] data)
{
    // Read the last 4 bytes to get the length
    byte[] lengthBuffer = new byte[4];
    Array.Copy(data, data.Length - 4, lengthBuffer, 0, 4);
    int uncompressedSize = BitConverter.ToInt32(lengthBuffer, 0);

    var buffer = new byte[uncompressedSize];
    using (var ms = new MemoryStream(data))
    {
        using (var gzip = new GZipStream(ms, CompressionMode.Decompress))
        {
            gzip.Read(buffer, 0, uncompressedSize);
        }
    }
    string json = Encoding.UTF8.GetString(buffer); 
    return json;
}
Haryono
  • 2,184
  • 1
  • 21
  • 14