node.jscompressionzlib

Cannot decompress zlib compressed file using NodeJS


I have a 22 byte payload that is compressed with ZLIB. I can decompress the file just fine in Java to the original 14 byte String using this snippet:

public static void main(String[] args) throws Exception {
    byte[] compressedData = readFile(INPUT_FILE);
    System.out.println("Compressed data (hex): " + bytesToHex(compressedData));
    System.out.println("Compressed data length: " + compressedData.length);

    byte[] uncompressedData = inflateData(compressedData, UNCOMPRESSED_LENGTH);
    String outputString = new String(uncompressedData);
    System.out.println("Uncompressed data: " + outputString);
}

public static byte[] readFile(String filePath) throws IOException {
    try (FileInputStream fis = new FileInputStream(filePath); FileChannel fileChannel = fis.getChannel()) {
        ByteBuffer buffer = ByteBuffer.allocate((int) fileChannel.size());
        fileChannel.read(buffer);
        return buffer.array();
    }
}

public static byte[] inflateData(byte[] compressedData, int uncompressedLength) throws DataFormatException, IOException {
    Inflater inflater = new Inflater();
    inflater.setInput(compressedData);
    byte[] uncompressedData = new byte[uncompressedLength];
    int resultLength = inflater.inflate(uncompressedData);
    if (resultLength != uncompressedLength) {
        throw new IOException("Unexpected uncompressed length: expected " + uncompressedLength + ", got " + resultLength);
    }
    inflater.end();
    return uncompressedData;
}

However in NodeJS I fail to inflate this file. I've tried playing around with the options and also tried Pako, but to no avail.

const compressed = fs.readFileSync(INPUT_FILE);
console.log(`Compressed data (hex): ${compressed.toString('hex')}`);
console.log(`Compressed data length: ${compressed.length}`);

const uncompressedData: Buffer = await inflateAsync(compressed);
console.log(`Decompressed data length: ${uncompressedData.length}`);

if (uncompressedData.length !== UNCOMPRESSED_LENGTH) {
  throw new Error(`Unexpected uncompressed length: expected ${UNCOMPRESSED_LENGTH}, got ${uncompressedData.length}`);
}

The current error is Error: unexpected end of file. I'm more than a bit stuck on this, do you have a clue what's going on?

FYI: the hexadecimal string of this 22 byte file is 789cf2cacfc8cbab5408c928cd4b492d02000000ffff and is outputted identical in both the Java and NodeJS code.


Solution

  • It is indeed an incomplete zlib stream. However you can make the NodeJS zlib play a bit more nicely using the finishFlush option. So in the end, the data is decompressed using:

    const uncompressedData: Buffer = inflateSync(compressed, { finishFlush: 1 });