简体   繁体   English

带有偏移量的 JavaScript 中的 GZip 解压缩

[英]GZip decompression in JavaScript with offset

An API that I am trying to use is returning base64 encoded responses.我尝试使用的 API 正在返回 base64 编码的响应。 The response is first compressed using GZip with 4 bits of offset and then base64 encoded.响应首先使用具有 4 位偏移量的 GZip 进行压缩,然后进行 base64 编码。 I tried parsing the response using JavaScript ( pako and zlib ) and in both cases, it failed.我尝试使用 JavaScript( pakozlib )解析响应,但在这两种情况下,它都失败了。 The API has an example of C# code on how should the response decompression work, but I don't really know how can I transform that into JavaScript. API 有一个 C# 代码示例,说明响应解压缩应该如何工作,但我真的不知道如何将其转换为 JavaScript。 So can anyone give me a hand transforming this function into JavaScript or just give me some tips on how to handle the 4 bytes offset?那么谁能帮我把这个函数转换成 JavaScript 或者只是给我一些关于如何处理 4 字节偏移量的提示? I didn't find anything relevant in the libraries' documentation.我在图书馆的文档中没有找到任何相关的内容。

public string Decompress(string value)
{
  byte[] gzBuffer = Convert.FromBase64String(value);
  using (MemoryStream ms = new MemoryStream())
  {
    int msgLength = BitConverter.ToInt32(gzBuffer, 0);
    ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
    byte[] buffer = new byte[msgLength];
    ms.Position = 0;
    using (System.IO.Compression.GZipStream zip = new System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Decompress))
    {
      zip.Read(buffer, 0, buffer.Length);
    }
    return System.Text.Encoding.Unicode.GetString(buffer, 0, buffer.Length);
   }
}

I'm going to use fflate (disclaimer, I'm the author) to do this.我将使用fflate (免责声明,我是作者)来做到这一点。 If you want to translate that function line for line:如果您想为该行翻译该函数行:

// This is ES6 code; if you want better browser compatibility
// use the ES5 variant.
import { gunzipSync, strToU8, strFromU8 } from 'fflate';
const decompress = str => {
  // atob converts Base64 to Latin-1
  // strToU8(str, true) converts Latin-1 to binary
  const bytes = strToU8(atob(str), true);
  // subarray creates a new view on the same memory buffer
  // gunzipSync synchronously decompresses
  // strFromU8 converts decompressed binary to UTF-8
  return strFromU8(gunzipSync(bytes.subarray(4)));
}

If you don't know what ES6 is:如果你不知道 ES6 是什么:

In your HTML file:在您的 HTML 文件中:

<script src="https://cdn.jsdelivr.net/npm/fflate/umd/index.js"></script>

In your JS:在你的 JS 中:

var decompress = function(str) {
  var bytes = fflate.strToU8(atob(str), true);
  return fflate.strFromU8(fflate.gunzipSync(bytes.subarray(4)));
}

I'd like to mention that streams are almost totally useless if you're going to accumulate into a string at the end, so the C# code is suboptimal.我想提一下,如果你要在最后累积成一个字符串,流几乎完全没用,所以 C# 代码是次优的。 At the same time, since you're using the standard library, it is the only option.同时,由于您使用的是标准库,因此它是唯一的选择。

In addition, I'd highly recommend using the callback variant (ie gunzip instead of gunzipSync ) if possible because that runs on a separate thread to avoid causing the browser to freeze.此外,如果可能的话,我强烈建议使用回调变体(即gunzip而不是gunzipSync ),因为它在单独的线程上运行以避免导致浏览器冻结。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM