2

I must inflate some data (csv file chunks actually) client side in JavaScript, and deflate it on server side in C#.

On client side I'm using pako, and it looks like this:

var fileReader = new FileReader();

fileReader.onload = function(progressEvent) {
    var arrayBuffer = this.result;
    var binData = new Uint8Array(arrayBuffer);

    var data = pako.deflate(binData);

    var dataBlob = new Blob(data, { "type": "application/zlib" });
    callback(dataBlob);
};

fileReader.readAsArrayBuffer(bytes);

It seems to be working well. I say "seem" because if I save the data received on server side, I get a string looking like this:

1201562201899117927731141602491...

I found out that ZLib compressed data is supposed to start with 0x78 and 0x9C, and 120 is decimal for 0x78 and 156 is decimal for 0x9C, so client side inflate seems OK.

Problem is on server side I can't manage to deflate the data. This is what my code looks like:

// Read past the first two bytes of the zlib header
inputStream.Seek(2, SeekOrigin.Begin);

using (var zipStream = new DeflateStream(inputStream, CompressionMode.Decompress))
using (FileStream fileStream = File.Create(filePath))
{
    zipStream.CopyTo(fileStream);
}

I get an error from DeflateStream constructor saying the data is not quite right.

Now here is what I gathered so far:

  • If I add a { "to": "string" } to pako.deflate, it returns some binary string instead of a Uint8Array. It looks quite like what I get when I inflate the data server side, so that's probably what C# DeflateStream is expecting.
  • Data is sent through XHR FormData, which expects a Blob, which seems to always transform the data to a decimal string.
  • I read the data on server side with HttpContent.ReadAsStreamAsync().

What do you think I should do to properly deflate the data server side?

Community
  • 1
  • 1
François G.
  • 267
  • 2
  • 10
  • Please take a look this, if may help: https://stackoverflow.com/a/66825721/1979406 using pako in client to zip. – Haryono Mar 27 '21 at 00:03

1 Answers1

0

Pass the data to the blob constructor in an array

var dataBlob = new Blob([data], { "type": "application/zlib" });

From MDN

Syntax

var aBlob = new Blob( array, options );

Parameters

  • array is an Array of ArrayBuffer, ArrayBufferView, Blob, DOMString objects, or a mix of any of such objects, that will be put inside the Blob.
Musa
  • 96,336
  • 17
  • 118
  • 137
  • Didn't thought of that. Originally the error was "Block length does not match with its complement.", whether or not I skip the first ZLib two bytes header. Now the error (with first two bytes skipped) is "Failed to construct a huffman tree using the length array. The stream might be corrupted.". I'll keep looking. – François G. Mar 18 '16 at 15:10
  • Is the result from `pako.deflate` a string? On the documentation page it looks like the return can be either string, array or Uint8Array. – Musa Mar 18 '16 at 15:25
  • Default is Uint8Array. With { "to": "string" } as option i'm getting the binary string that you suggested I wrap into an array for the Blob constructor. They DO say it can return an array, but don't say how. – François G. Mar 18 '16 at 15:31
  • Did you try the blob constructor with the Uint8Array data inside an array? – Musa Mar 18 '16 at 16:04
  • You are right! It works! Thank your very much. Hope it will be helpful to someone else... – François G. Mar 18 '16 at 16:26
  • I know I'm a little late but can you post your entire complete solution if your still have it? Kinda hard to follow what ended up working. Thank – Rafi Dec 05 '19 at 15:17