【问题标题】:Javascript GZIP and btoa and decompress with C#Javascript GZIP 和 btoa 并使用 C# 解压缩
【发布时间】:2019-04-14 21:47:45
【问题描述】:

我正在开发一个应用程序,我使用 pako.gzip 压缩大型 JSON 数据,然后使用 btoa 函数将其设为 base64string,以便将数据发布到服务器。在我写的javascript中:

    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
    });

问题是我需要在发布后在 C# 代码中再次解压缩数据,以便对其进行其他处理。在我写的 C# 代码中:

    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 = "";

我在这里得到错误

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

解码时发现无效数据。

任何帮助将数据解压回 C# 将不胜感激

EDIT:总结需要做的事情 javascript 执行以下操作:

纯文本 >> 到 >> gzip 字节 >> 到 >> base64 字符串

我需要 C# 来做相反的事情:

Base64 >> to >> unzip bytes >> to >> 纯文本

【问题讨论】:

  • 你有想过这个吗?
  • 不,我使用另一种方法在 Javascript 中压缩为 LZString 并在 C# 中解压缩
  • 好吧,我根据自己的需要想出来了。在下面发布作为您问题的答案
  • 干得好,但据我所知 LZString 比 GZip 更强大,请查看此链接,了解如何在 C# 和 javascript 中使用 LZString,反之亦然。 devananddhage.wordpress.com/2015/04/30/…
  • 谢谢。你有关于压缩多少的统计数据吗?我知道这取决于输入数据。对我来说 gzip 压缩了 30%。 LZString 做得更多?

标签: base64 compression gzip


【解决方案1】:

假设js如下:

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

这是使用 GZip 压缩/解压缩的正确 c# 代码:取自 https://*.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());
            }
        }
    }
}

如下调用:

value = _compressor.Unzip(Convert.FromBase64CharArray(value.ToCharArray(), 0, value.Length));

【讨论】:

    【解决方案2】:

    在客户端使用:

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

    发送为:'Content-Type': 'application/octet-stream'

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

    然后在 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;
    }
    

    【讨论】: