Перейти к содержанию

Zlib

latest

Стабильность: 2 – Стабильная

АПИ является удовлетворительным. Совместимость с NPM имеет высший приоритет и не будет нарушена кроме случаев явной необходимости.

Модуль node:zlib предоставляет сжатие на базе Gzip, Deflate/Inflate, Brotli и Zstd.

Подключение:

1
import zlib from 'node:zlib';
1
const zlib = require('node:zlib');

Сжатие и распаковка опираются на Streams API Node.js.

Сжать или распаковать поток (например, файл) можно, пропустив исходный поток через Transform модуля zlib в целевой поток:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import {
  createReadStream,
  createWriteStream,
} from 'node:fs';
import process from 'node:process';
import { createGzip } from 'node:zlib';
import { pipeline } from 'node:stream';

const gzip = createGzip();
const source = createReadStream('input.txt');
const destination = createWriteStream('input.txt.gz');

pipeline(source, gzip, destination, (err) => {
  if (err) {
    console.error('An error occurred:', err);
    process.exitCode = 1;
  }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
const {
  createReadStream,
  createWriteStream,
} = require('node:fs');
const process = require('node:process');
const { createGzip } = require('node:zlib');
const { pipeline } = require('node:stream');

const gzip = createGzip();
const source = createReadStream('input.txt');
const destination = createWriteStream('input.txt.gz');

pipeline(source, gzip, destination, (err) => {
  if (err) {
    console.error('An error occurred:', err);
    process.exitCode = 1;
  }
});

Или через промисный API pipeline:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import {
  createReadStream,
  createWriteStream,
} from 'node:fs';
import { createGzip } from 'node:zlib';
import { pipeline } from 'node:stream/promises';

async function do_gzip(input, output) {
  const gzip = createGzip();
  const source = createReadStream(input);
  const destination = createWriteStream(output);
  await pipeline(source, gzip, destination);
}

await do_gzip('input.txt', 'input.txt.gz');
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
const {
  createReadStream,
  createWriteStream,
} = require('node:fs');
const process = require('node:process');
const { createGzip } = require('node:zlib');
const { pipeline } = require('node:stream/promises');

async function do_gzip(input, output) {
  const gzip = createGzip();
  const source = createReadStream(input);
  const destination = createWriteStream(output);
  await pipeline(source, gzip, destination);
}

do_gzip('input.txt', 'input.txt.gz')
  .catch((err) => {
    console.error('An error occurred:', err);
    process.exitCode = 1;
  });

Данные можно сжать или распаковать и за один проход:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import process from 'node:process';
import { Buffer } from 'node:buffer';
import { deflate, unzip } from 'node:zlib';

const input = '.................................';
deflate(input, (err, buffer) => {
  if (err) {
    console.error('An error occurred:', err);
    process.exitCode = 1;
  }
  console.log(buffer.toString('base64'));
});

const buffer = Buffer.from('eJzT0yMAAGTvBe8=', 'base64');
unzip(buffer, (err, buffer) => {
  if (err) {
    console.error('An error occurred:', err);
    process.exitCode = 1;
  }
  console.log(buffer.toString());
});

// Или через промисы

import { promisify } from 'node:util';
const do_unzip = promisify(unzip);

const unzippedBuffer = await do_unzip(buffer);
console.log(unzippedBuffer.toString());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const { deflate, unzip } = require('node:zlib');

const input = '.................................';
deflate(input, (err, buffer) => {
  if (err) {
    console.error('An error occurred:', err);
    process.exitCode = 1;
  }
  console.log(buffer.toString('base64'));
});

const buffer = Buffer.from('eJzT0yMAAGTvBe8=', 'base64');
unzip(buffer, (err, buffer) => {
  if (err) {
    console.error('An error occurred:', err);
    process.exitCode = 1;
  }
  console.log(buffer.toString());
});

// Или через промисы

const { promisify } = require('node:util');
const do_unzip = promisify(unzip);

do_unzip(buffer)
  .then((buf) => console.log(buf.toString()))
  .catch((err) => {
    console.error('An error occurred:', err);
    process.exitCode = 1;
  });

Пул потоков и производительность

Все API zlib, кроме явно синхронных, используют внутренний пул потоков Node.js. Это может давать неожиданные эффекты и ограничивать производительность.

Одновременное создание и использование большого числа объектов zlib может вызывать сильную фрагментацию памяти.

1
2
3
4
5
6
7
8
9
import zlib from 'node:zlib';
import { Buffer } from 'node:buffer';

const payload = Buffer.from('This is some data');

// WARNING: DO NOT DO THIS!
for (let i = 0; i < 30000; ++i) {
  zlib.deflate(payload, (err, buffer) => {});
}
1
2
3
4
5
6
7
8
const zlib = require('node:zlib');

const payload = Buffer.from('This is some data');

// WARNING: DO NOT DO THIS!
for (let i = 0; i < 30000; ++i) {
  zlib.deflate(payload, (err, buffer) => {});
}

В примере одновременно создаётся 30 000 экземпляров deflate. Из‑за особенностей выделения и освобождения памяти в ОС это может привести к сильной фрагментации.

Рекомендуется кэшировать результаты сжатия, чтобы не повторять работу.

Сжатие HTTP-запросов и ответов

Модуль node:zlib позволяет поддержать механизмы gzip, deflate, br и zstd для content-encoding из HTTP.

Заголовок Accept-Encoding в запросе указывает, какие кодировки сжатия принимает клиент. Заголовок Content-Encoding — какие кодировки сжатия фактически применены к сообщению.

Примеры ниже сильно упрощены. Кодирование через zlib может быть дорогим, результаты стоит кэшировать. См. настройку использования памяти о компромиссе скорость/память/степень сжатия для zlib.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Пример клиентского запроса
import fs from 'node:fs';
import zlib from 'node:zlib';
import http from 'node:http';
import process from 'node:process';
import { pipeline } from 'node:stream';

const request = http.get({ host: 'example.com',
                           path: '/',
                           port: 80,
                           headers: { 'Accept-Encoding': 'br,gzip,deflate,zstd' } });
request.on('response', (response) => {
  const output = fs.createWriteStream('example.com_index.html');

  const onError = (err) => {
    if (err) {
      console.error('An error occurred:', err);
      process.exitCode = 1;
    }
  };

  switch (response.headers['content-encoding']) {
    case 'br':
      pipeline(response, zlib.createBrotliDecompress(), output, onError);
      break;
    // Можно также использовать zlib.createUnzip() для обоих случаев ниже:
    case 'gzip':
      pipeline(response, zlib.createGunzip(), output, onError);
      break;
    case 'deflate':
      pipeline(response, zlib.createInflate(), output, onError);
      break;
    case 'zstd':
      pipeline(response, zlib.createZstdDecompress(), output, onError);
      break;
    default:
      pipeline(response, output, onError);
      break;
  }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// Пример клиентского запроса
const zlib = require('node:zlib');
const http = require('node:http');
const fs = require('node:fs');
const { pipeline } = require('node:stream');

const request = http.get({ host: 'example.com',
                           path: '/',
                           port: 80,
                           headers: { 'Accept-Encoding': 'br,gzip,deflate,zstd' } });
request.on('response', (response) => {
  const output = fs.createWriteStream('example.com_index.html');

  const onError = (err) => {
    if (err) {
      console.error('An error occurred:', err);
      process.exitCode = 1;
    }
  };

  switch (response.headers['content-encoding']) {
    case 'br':
      pipeline(response, zlib.createBrotliDecompress(), output, onError);
      break;
    // Можно также использовать zlib.createUnzip() для обоих случаев ниже:
    case 'gzip':
      pipeline(response, zlib.createGunzip(), output, onError);
      break;
    case 'deflate':
      pipeline(response, zlib.createInflate(), output, onError);
      break;
    case 'zstd':
      pipeline(response, zlib.createZstdDecompress(), output, onError);
      break;
    default:
      pipeline(response, output, onError);
      break;
  }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Пример сервера
// Запускать gzip на каждый запрос дорого.
// Эффективнее кэшировать сжатый буфер.
import zlib from 'node:zlib';
import http from 'node:http';
import fs from 'node:fs';
import { pipeline } from 'node:stream';

http.createServer((request, response) => {
  const raw = fs.createReadStream('index.html');
  // Держать сжатую и несжатую версии ресурса.
  response.setHeader('Vary', 'Accept-Encoding');
  const acceptEncoding = request.headers['accept-encoding'] || '';

  const onError = (err) => {
    if (err) {
      // При ошибке мало что сделать: ответ 200 уже ушёл,
      // часть данных могла быть отправлена клиенту.
      // Завершаем ответ и пишем ошибку в журнал.
      response.end();
      console.error('An error occurred:', err);
    }
  };

  // Примечание: это не полноценный разбор Accept-Encoding.
  // См. https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
  if (/\bdeflate\b/.test(acceptEncoding)) {
    response.writeHead(200, { 'Content-Encoding': 'deflate' });
    pipeline(raw, zlib.createDeflate(), response, onError);
  } else if (/\bgzip\b/.test(acceptEncoding)) {
    response.writeHead(200, { 'Content-Encoding': 'gzip' });
    pipeline(raw, zlib.createGzip(), response, onError);
  } else if (/\bbr\b/.test(acceptEncoding)) {
    response.writeHead(200, { 'Content-Encoding': 'br' });
    pipeline(raw, zlib.createBrotliCompress(), response, onError);
  } else if (/\bzstd\b/.test(acceptEncoding)) {
    response.writeHead(200, { 'Content-Encoding': 'zstd' });
    pipeline(raw, zlib.createZstdCompress(), response, onError);
  } else {
    response.writeHead(200, {});
    pipeline(raw, response, onError);
  }
}).listen(1337);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Пример сервера
// Запускать gzip на каждый запрос дорого.
// Эффективнее кэшировать сжатый буфер.
const zlib = require('node:zlib');
const http = require('node:http');
const fs = require('node:fs');
const { pipeline } = require('node:stream');

http.createServer((request, response) => {
  const raw = fs.createReadStream('index.html');
  // Держать сжатую и несжатую версии ресурса.
  response.setHeader('Vary', 'Accept-Encoding');
  const acceptEncoding = request.headers['accept-encoding'] || '';

  const onError = (err) => {
    if (err) {
      // При ошибке мало что сделать: ответ 200 уже ушёл,
      // часть данных могла быть отправлена клиенту.
      // Завершаем ответ и пишем ошибку в журнал.
      response.end();
      console.error('An error occurred:', err);
    }
  };

  // Примечание: это не полноценный разбор Accept-Encoding.
  // См. https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
  if (/\bdeflate\b/.test(acceptEncoding)) {
    response.writeHead(200, { 'Content-Encoding': 'deflate' });
    pipeline(raw, zlib.createDeflate(), response, onError);
  } else if (/\bgzip\b/.test(acceptEncoding)) {
    response.writeHead(200, { 'Content-Encoding': 'gzip' });
    pipeline(raw, zlib.createGzip(), response, onError);
  } else if (/\bbr\b/.test(acceptEncoding)) {
    response.writeHead(200, { 'Content-Encoding': 'br' });
    pipeline(raw, zlib.createBrotliCompress(), response, onError);
  } else if (/\bzstd\b/.test(acceptEncoding)) {
    response.writeHead(200, { 'Content-Encoding': 'zstd' });
    pipeline(raw, zlib.createZstdCompress(), response, onError);
  } else {
    response.writeHead(200, {});
    pipeline(raw, response, onError);
  }
}).listen(1337);

По умолчанию методы zlib при распаковке усечённых данных выбрасывают ошибку. Если известно, что данные неполные, или нужно лишь просмотреть начало сжатого файла, поведение по умолчанию можно изменить, выбрав другой режим сброса для последнего фрагмента входных данных:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// Усечённая версия буфера из примеров выше
const buffer = Buffer.from('eJzT0yMA', 'base64');

zlib.unzip(
  buffer,
  // Для Brotli эквивалент — zlib.constants.BROTLI_OPERATION_FLUSH.
  // Для Zstd эквивалент — zlib.constants.ZSTD_e_flush.
  { finishFlush: zlib.constants.Z_SYNC_FLUSH },
  (err, buffer) => {
    if (err) {
      console.error('An error occurred:', err);
      process.exitCode = 1;
    }
    console.log(buffer.toString());
  });

В других случаях ошибок (например, при неверном формате входных данных) поведение не меняется. Так нельзя отличить преждевременный конец входа от отсутствия проверок целостности — нужно вручную убедиться, что результат распаковки корректен.

Настройка использования памяти

Потоки на базе zlib

Из zlib/zconf.h, адаптировано для Node.js:

Требования к памяти для deflate (в байтах):

1
(1 << (windowBits + 2)) + (1 << (memLevel + 9))

То есть 128K при windowBits = 15 плюс 128K при memLevel = 8 (значения по умолчанию) плюс несколько килобайт на служебные объекты.

Чтобы снизить потребление памяти по умолчанию с 256K до 128K, задайте:

1
const options = { windowBits: 14, memLevel: 7 };

Обычно при этом сжатие становится слабее.

Для inflate требования к памяти (в байтах): 1 << windowBits. То есть 32K при windowBits = 15 (по умолчанию) плюс несколько килобайт на мелкие объекты.

Плюс один внутренний выходной буфер-слэб размера chunkSize (по умолчанию 16K).

На скорость сжатия zlib больше всего влияет параметр level. Выше уровень — лучше сжатие, но дольше время. Ниже уровень — слабее сжатие, но быстрее.

В целом большие значения параметров памяти позволяют Node.js реже вызывать zlib, обрабатывая больше данных за один write. Это ещё один рычаг скорости в обмен на память.

Потоки на базе Brotli

Для потоков Brotli есть аналоги опций zlib, но с другими допустимыми диапазонами:

  • опция level у zlib соответствует BROTLI_PARAM_QUALITY у Brotli;
  • опция windowBits у zlib соответствует BROTLI_PARAM_LGWIN у Brotli.

Подробнее о параметрах Brotli — ниже.

Потоки на базе Zstd

Стабильность: 1 – Экспериментальная

Фича изменяется и не допускается флагом командной строки. Может быть изменена или удалена в последующих версиях.

Для потоков Zstd есть аналоги опций zlib, но с другими диапазонами:

  • опция level у zlib соответствует ZSTD_c_compressionLevel у Zstd;
  • опция windowBits у zlib соответствует ZSTD_c_windowLog у Zstd.

Подробнее о параметрах Zstd — ниже.

Сброс (flush)

Вызов .flush() на потоке сжатия заставляет zlib отдать максимум выходных данных на текущий момент. Качество сжатия может ухудшиться, зато данные быстрее становятся доступны.

В примере flush() используется для отправки клиенту частичного сжатого HTTP-ответа:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import zlib from 'node:zlib';
import http from 'node:http';
import { pipeline } from 'node:stream';

http.createServer((request, response) => {
  // Для краткости проверки Accept-Encoding опущены.
  response.writeHead(200, { 'content-encoding': 'gzip' });
  const output = zlib.createGzip();
  let i;

  pipeline(output, response, (err) => {
    if (err) {
      // При ошибке мало что сделать: ответ 200 уже ушёл,
      // часть данных могла быть отправлена клиенту.
      // Завершаем ответ и пишем ошибку в журнал.
      clearInterval(i);
      response.end();
      console.error('An error occurred:', err);
    }
  });

  i = setInterval(() => {
    output.write(`The current time is ${Date()}\n`, () => {
      // Данные переданы в zlib, но алгоритм мог буферизовать их для лучшего сжатия.
      // Вызов .flush() отдаёт данные, как только клиент готов их принять.
      output.flush();
    });
  }, 1000);
}).listen(1337);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const zlib = require('node:zlib');
const http = require('node:http');
const { pipeline } = require('node:stream');

http.createServer((request, response) => {
  // Для краткости проверки Accept-Encoding опущены.
  response.writeHead(200, { 'content-encoding': 'gzip' });
  const output = zlib.createGzip();
  let i;

  pipeline(output, response, (err) => {
    if (err) {
      // При ошибке мало что сделать: ответ 200 уже ушёл,
      // часть данных могла быть отправлена клиенту.
      // Завершаем ответ и пишем ошибку в журнал.
      clearInterval(i);
      response.end();
      console.error('An error occurred:', err);
    }
  });

  i = setInterval(() => {
    output.write(`The current time is ${Date()}\n`, () => {
      // Данные переданы в zlib, но алгоритм мог буферизовать их для лучшего сжатия.
      // Вызов .flush() отдаёт данные, как только клиент готов их принять.
      output.flush();
    });
  }, 1000);
}).listen(1337);

Константы

Константы zlib

Все константы из zlib.h также доступны в require('node:zlib').constants. В обычной работе они часто не нужны; они описаны, чтобы наличие не удивляло. Раздел почти взят из документации zlib.

Раньше константы были доступны прямо из require('node:zlib'), например zlib.Z_NO_FLUSH. Прямой доступ к константам по-прежнему возможен, но устарел.

Допустимые значения сброса:

  • zlib.constants.Z_NO_FLUSH
  • zlib.constants.Z_PARTIAL_FLUSH
  • zlib.constants.Z_SYNC_FLUSH
  • zlib.constants.Z_FULL_FLUSH
  • zlib.constants.Z_FINISH
  • zlib.constants.Z_BLOCK

Коды возврата функций сжатия/распаковки. Отрицательные — ошибки, положительные — особые, но нормальные события.

  • zlib.constants.Z_OK
  • zlib.constants.Z_STREAM_END
  • zlib.constants.Z_NEED_DICT
  • zlib.constants.Z_ERRNO
  • zlib.constants.Z_STREAM_ERROR
  • zlib.constants.Z_DATA_ERROR
  • zlib.constants.Z_MEM_ERROR
  • zlib.constants.Z_BUF_ERROR
  • zlib.constants.Z_VERSION_ERROR

Уровни сжатия:

  • zlib.constants.Z_NO_COMPRESSION
  • zlib.constants.Z_BEST_SPEED
  • zlib.constants.Z_BEST_COMPRESSION
  • zlib.constants.Z_DEFAULT_COMPRESSION

Стратегия сжатия:

  • zlib.constants.Z_FILTERED
  • zlib.constants.Z_HUFFMAN_ONLY
  • zlib.constants.Z_RLE
  • zlib.constants.Z_FIXED
  • zlib.constants.Z_DEFAULT_STRATEGY

Константы Brotli

Для потоков на базе Brotli доступны дополнительные опции и константы:

Операции сброса

Допустимые операции сброса для потоков Brotli:

  • zlib.constants.BROTLI_OPERATION_PROCESS (по умолчанию для всех операций)
  • zlib.constants.BROTLI_OPERATION_FLUSH (по умолчанию при вызове .flush())
  • zlib.constants.BROTLI_OPERATION_FINISH (по умолчанию для последнего фрагмента)
  • zlib.constants.BROTLI_OPERATION_EMIT_METADATA
  • В контексте Node.js эту операцию использовать сложно: потоковый уровень не даёт ясно знать, какие данные попадут в кадр; через API Node.js эти данные сейчас не прочитать.

Параметры компрессора

У кодировщиков Brotli можно задать параметры, влияющие на эффективность и скорость. Ключи и значения доступны как свойства объекта zlib.constants.

Основные параметры:

  • BROTLI_PARAM_MODE
  • BROTLI_MODE_GENERIC (по умолчанию)
  • BROTLI_MODE_TEXT, подстроен под UTF-8 текст
  • BROTLI_MODE_FONT, подстроен под шрифты WOFF 2.0
  • BROTLI_PARAM_QUALITY
  • От BROTLI_MIN_QUALITY до BROTLI_MAX_QUALITY, по умолчанию BROTLI_DEFAULT_QUALITY.
  • BROTLI_PARAM_SIZE_HINT
  • Ожидаемый размер входа (целое); 0, если размер неизвестен.

Дополнительные флаги для тонкой настройки алгоритма и памяти:

  • BROTLI_PARAM_LGWIN
  • От BROTLI_MIN_WINDOW_BITS до BROTLI_MAX_WINDOW_BITS, по умолчанию BROTLI_DEFAULT_WINDOW, или до BROTLI_LARGE_MAX_WINDOW_BITS, если установлен флаг BROTLI_PARAM_LARGE_WINDOW.
  • BROTLI_PARAM_LGBLOCK
  • От BROTLI_MIN_INPUT_BLOCK_BITS до BROTLI_MAX_INPUT_BLOCK_BITS.
  • BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING
  • Boolean: снижает степень сжатия в пользу скорости распаковки.
  • BROTLI_PARAM_LARGE_WINDOW
  • Boolean: режим «Large Window Brotli» (несовместим с форматом Brotli в RFC 7932).
  • BROTLI_PARAM_NPOSTFIX
  • От 0 до BROTLI_MAX_NPOSTFIX.
  • BROTLI_PARAM_NDIRECT
  • От 0 до 15 << NPOSTFIX с шагом 1 << NPOSTFIX.

Параметры декомпрессора

Дополнительные опции управления распаковкой:

  • BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION
  • Boolean: влияет на схему внутренних выделений памяти.
  • BROTLI_DECODER_PARAM_LARGE_WINDOW
  • Boolean: режим «Large Window Brotli» (несовместим с RFC 7932).

Константы Zstd

Стабильность: 1 – Экспериментальная

Фича изменяется и не допускается флагом командной строки. Может быть изменена или удалена в последующих версиях.

Для потоков на базе Zstd доступны дополнительные опции и константы:

Операции сброса

Допустимые операции сброса для потоков Zstd:

  • zlib.constants.ZSTD_e_continue (по умолчанию для всех операций)
  • zlib.constants.ZSTD_e_flush (по умолчанию при вызове .flush())
  • zlib.constants.ZSTD_e_end (по умолчанию для последнего фрагмента)

Параметры компрессора

У кодировщиков Zstd можно задать параметры, влияющие на эффективность и скорость. Ключи и значения доступны как свойства zlib.constants.

Основные параметры:

  • ZSTD_c_compressionLevel
  • Параметры сжатия по таблице уровней; по умолчанию ZSTD_CLEVEL_DEFAULT==3.
  • ZSTD_c_strategy
  • Стратегия сжатия;
  • возможные значения — в разделе стратегий ниже.

Стратегии

Константы для параметра ZSTD_c_strategy:

  • zlib.constants.ZSTD_fast
  • zlib.constants.ZSTD_dfast
  • zlib.constants.ZSTD_greedy
  • zlib.constants.ZSTD_lazy
  • zlib.constants.ZSTD_lazy2
  • zlib.constants.ZSTD_btlazy2
  • zlib.constants.ZSTD_btopt
  • zlib.constants.ZSTD_btultra
  • zlib.constants.ZSTD_btultra2

Пример:

1
2
3
4
5
const stream = zlib.createZstdCompress({
  params: {
    [zlib.constants.ZSTD_c_strategy]: zlib.constants.ZSTD_btultra,
  },
});

Заявленный размер исходных данных

Ожидаемый полный размер несжатого входа можно задать через opts.pledgedSrcSize. Если в конце входа размер не совпадает, сжатие завершится с кодом ZSTD_error_srcSize_wrong.

Параметры декомпрессора

Дополнительные опции распаковки:

  • ZSTD_d_windowLogMax
  • Верхний предел (степень двойки), выше которого потоковый API откажется выделять буфер, чтобы защитить хост от чрезмерных требований к памяти.

Класс: Options

Добавлено в: v0.11.1

У каждого класса на базе zlib есть объект options. Он необязателен.

Часть полей имеет смысл только при сжатии и игнорируется классами распаковки.

Подробнее см. документацию deflateInit2 и inflateInit2.

Класс: BrotliOptions

Добавлено в: v11.7.0

У каждого класса на базе Brotli есть объект options. Все поля необязательны.

Например:

1
2
3
4
5
6
7
8
const stream = zlib.createBrotliCompress({
  chunkSize: 32 * 1024,
  params: {
    [zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
    [zlib.constants.BROTLI_PARAM_QUALITY]: 4,
    [zlib.constants.BROTLI_PARAM_SIZE_HINT]: fs.statSync(inputFile).size,
  },
});

Класс: zlib.BrotliCompress

Сжатие данных алгоритмом Brotli.

Класс: zlib.BrotliDecompress

Распаковка данных алгоритмом Brotli.

Класс: zlib.Deflate

Сжатие через deflate.

Класс: zlib.DeflateRaw

Сжатие через deflate без добавления заголовка zlib.

Класс: zlib.Gunzip

Добавлено в: v0.5.8

Распаковка потока gzip.

Класс: zlib.Gzip

Сжатие через gzip.

Класс: zlib.Inflate

Добавлено в: v0.5.8

Распаковка потока deflate.

Класс: zlib.InflateRaw

Добавлено в: v0.5.8

Распаковка «сырого» deflate.

Класс: zlib.Unzip

Распаковка потока, сжатого Gzip или Deflate, с автоматическим определением заголовка.

Класс: zlib.ZlibBase

Добавлено в: v0.5.8

Не экспортируется модулем node:zlib. Описан как базовый класс для компрессоров/декомпрессоров.

Наследует stream.Transform, поэтому объекты node:zlib можно использовать в цепочках pipe и подобных операциях с потоками.

zlib.bytesWritten

Свойство zlib.bytesWritten задаёт число байт, записанных в движок до обработки (сжатия или распаковки — в зависимости от производного класса).

zlib.close([callback])

Закрывает нижележащий дескриптор.

zlib.flush([kind, ]callback)

  • kind По умолчанию: zlib.constants.Z_FULL_FLUSH для потоков на zlib, zlib.constants.BROTLI_OPERATION_FLUSH для потоков на Brotli.
  • callback <Function>

Сбрасывает накопленные данные. Вызывать без нужды не стоит: преждевременный flush ухудшает сжатие.

Сбрасывается только внутреннее состояние zlib, не уровень потоков. Поведение как у обычного .write(): ставится в очередь после других записей и даёт выход, когда из потока читают данные.

zlib.params(level, strategy, callback)

Только для потоков на zlib, не для Brotli.

Динамически меняет уровень и стратегию сжатия. Только для алгоритма deflate.

zlib.reset()

Сбрасывает компрессор/декомпрессор к настройкам по умолчанию. Только для inflate и deflate.

Класс: ZstdOptions

Стабильность: 1 – Экспериментальная

Фича изменяется и не допускается флагом командной строки. Может быть изменена или удалена в последующих версиях.

У каждого класса на базе Zstd есть объект options. Все поля необязательны.

  • flush <integer> По умолчанию: zlib.constants.ZSTD_e_continue
  • finishFlush <integer> По умолчанию: zlib.constants.ZSTD_e_end
  • chunkSize <integer> По умолчанию: 16 * 1024
  • params <Object> Объект «ключ — значение» с индексированными параметрами Zstd.
  • maxOutputLength <integer> Ограничивает размер выхода у вспомогательных методов. По умолчанию: buffer.kMaxLength
  • info <boolean> При true возвращается объект с buffer и engine. По умолчанию: false
  • dictionary <Buffer> Необязательный словарь для повышения эффективности сжатия/распаковки данных с общими с словарём шаблонами.

Например:

1
2
3
4
5
6
7
const stream = zlib.createZstdCompress({
  chunkSize: 32 * 1024,
  params: {
    [zlib.constants.ZSTD_c_compressionLevel]: 10,
    [zlib.constants.ZSTD_c_checksumFlag]: 1,
  },
});

Класс: zlib.ZstdCompress

Стабильность: 1 – Экспериментальная

Фича изменяется и не допускается флагом командной строки. Может быть изменена или удалена в последующих версиях.

Сжатие данных алгоритмом Zstd.

Класс: zlib.ZstdDecompress

Стабильность: 1 – Экспериментальная

Фича изменяется и не допускается флагом командной строки. Может быть изменена или удалена в последующих версиях.

Распаковка данных алгоритмом Zstd.

zlib.constants

Объект с перечислением констант, связанных с Zlib.

zlib.crc32(data[, value])

  • data <string> | <Buffer> | <TypedArray> | <DataView> Если data — строка, перед вычислением она кодируется в UTF-8.
  • value <integer> Необязательное начальное значение. Должно быть 32-битным беззнаковым целым. По умолчанию: 0
  • Возвращает: <integer> 32-битное беззнаковое целое с контрольной суммой.

Вычисляет 32-битную контрольную сумму CRC для data. Если задан value, оно используется как начальное значение суммы, иначе начинаем с 0.

CRC предназначен для контрольных сумм и обнаружения ошибок при передаче данных. Для криптографической аутентификации не подходит.

Для согласованности с другими API строка data перед вычислением кодируется в UTF-8. Если Node.js используется только для вычисления и сравнения сумм, это согласуется с API, где по умолчанию UTF-8.

Некоторые сторонние библиотеки считают сумму по строке через str.charCodeAt(), чтобы работать в браузере. Чтобы совпасть с такой библиотекой в браузере, лучше использовать ту же библиотеку и в Node.js, если она там есть. Если нужно именно zlib.crc32() для сопоставления с такой библиотекой:

  1. Если библиотека принимает Uint8Array, в браузере закодируйте строку в Uint8Array через TextEncoder в UTF-8 и считайте сумму по этим байтам.
  2. Если библиотека берёт только строку и опирается на str.charCodeAt(), на стороне Node.js преобразуйте строку в буфер через Buffer.from(str, 'utf16le').
1
2
3
4
5
6
7
8
import zlib from 'node:zlib';
import { Buffer } from 'node:buffer';

let crc = zlib.crc32('hello');  // 907060870
crc = zlib.crc32('world', crc);  // 4192936109

crc = zlib.crc32(Buffer.from('hello', 'utf16le'));  // 1427272415
crc = zlib.crc32(Buffer.from('world', 'utf16le'), crc);  // 4150509955
1
2
3
4
5
6
7
8
const zlib = require('node:zlib');
const { Buffer } = require('node:buffer');

let crc = zlib.crc32('hello');  // 907060870
crc = zlib.crc32('world', crc);  // 4192936109

crc = zlib.crc32(Buffer.from('hello', 'utf16le'));  // 1427272415
crc = zlib.crc32(Buffer.from('world', 'utf16le'), crc);  // 4150509955

zlib.createBrotliCompress([options])

Создаёт и возвращает новый объект BrotliCompress.

zlib.createBrotliDecompress([options])

Создаёт и возвращает новый объект BrotliDecompress.

zlib.createDeflate([options])

Создаёт и возвращает новый объект Deflate.

zlib.createDeflateRaw([options])

Создаёт и возвращает новый объект DeflateRaw.

Обновление zlib с 1.2.8 до 1.2.11 изменило поведение при windowBits = 8 для потоков raw deflate: zlib автоматически поднимала windowBits до 9, если изначально было 8. В новых zlib при этом выбрасывается исключение; Node.js восстановил прежнее поведение (8 → 9), так как при windowBits = 9 получается поток, фактически использующий только 8-битное окно.

zlib.createGunzip([options])

Создаёт и возвращает новый объект Gunzip.

zlib.createGzip([options])

Создаёт и возвращает новый объект Gzip. См. пример.

zlib.createInflate([options])

Создаёт и возвращает новый объект Inflate.

zlib.createInflateRaw([options])

Создаёт и возвращает новый объект InflateRaw.

zlib.createUnzip([options])

Создаёт и возвращает новый объект Unzip.

zlib.createZstdCompress([options])

Стабильность: 1 – Экспериментальная

Фича изменяется и не допускается флагом командной строки. Может быть изменена или удалена в последующих версиях.

Создаёт и возвращает новый объект ZstdCompress.

zlib.createZstdDecompress([options])

Стабильность: 1 – Экспериментальная

Фича изменяется и не допускается флагом командной строки. Может быть изменена или удалена в последующих версиях.

Создаёт и возвращает новый объект ZstdDecompress.

Вспомогательные методы

Все эти методы принимают первым аргументом Buffer, TypedArray, DataView, ArrayBuffer или строку, вторым (необязательно) — опции для классов zlib, и вызывают переданный callback в виде callback(error, result).

У каждого метода есть синхронный вариант *Sync с теми же аргументами, но без callback.

zlib.brotliCompress(buffer[, options], callback)

zlib.brotliCompressSync(buffer[, options])

Сжимает фрагмент данных через BrotliCompress.

zlib.brotliDecompress(buffer[, options], callback)

zlib.brotliDecompressSync(buffer[, options])

Распаковывает фрагмент данных через BrotliDecompress.

zlib.deflate(buffer[, options], callback)

Добавлено в: v0.6.0

zlib.deflateSync(buffer[, options])

Добавлено в: v0.11.12

Сжимает фрагмент данных через Deflate.

zlib.deflateRaw(buffer[, options], callback)

Добавлено в: v0.6.0

zlib.deflateRawSync(buffer[, options])

Добавлено в: v0.11.12

Сжимает фрагмент данных через DeflateRaw.

zlib.gunzip(buffer[, options], callback)

Добавлено в: v0.6.0

zlib.gunzipSync(buffer[, options])

Добавлено в: v0.11.12

Распаковывает фрагмент данных через Gunzip.

zlib.gzip(buffer[, options], callback)

Добавлено в: v0.6.0

zlib.gzipSync(buffer[, options])

Добавлено в: v0.11.12

Сжимает фрагмент данных через Gzip.

zlib.inflate(buffer[, options], callback)

Добавлено в: v0.6.0

zlib.inflateSync(buffer[, options])

Добавлено в: v0.11.12

Распаковывает фрагмент данных через Inflate.

zlib.inflateRaw(buffer[, options], callback)

Добавлено в: v0.6.0

zlib.inflateRawSync(buffer[, options])

Добавлено в: v0.11.12

Распаковывает фрагмент данных через InflateRaw.

zlib.unzip(buffer[, options], callback)

Добавлено в: v0.6.0

zlib.unzipSync(buffer[, options])

Добавлено в: v0.11.12

Распаковывает фрагмент данных через Unzip.

zlib.zstdCompress(buffer[, options], callback)

Стабильность: 1 – Экспериментальная

Фича изменяется и не допускается флагом командной строки. Может быть изменена или удалена в последующих версиях.

zlib.zstdCompressSync(buffer[, options])

Стабильность: 1 – Экспериментальная

Фича изменяется и не допускается флагом командной строки. Может быть изменена или удалена в последующих версиях.

Сжимает фрагмент данных через ZstdCompress.

zlib.zstdDecompress(buffer[, options], callback)

zlib.zstdDecompressSync(buffer[, options])

Стабильность: 1 – Экспериментальная

Фича изменяется и не допускается флагом командной строки. Может быть изменена или удалена в последующих версиях.

Распаковывает фрагмент данных через ZstdDecompress.

Комментарии