Zlib
Модуль zlib предоставляет функциональность сжатия, реализованную с использованием Gzip и Deflate/Inflate. К нему можно получить доступ следующим образом:
const zlib = require('zlib');
Сжатие или расжатие потока (например, файла) может быть выполнено путем перенаправления данных исходного потока через поток zlib в целевой поток:
const gzip = zlib.createGzip();
const fs = require('fs');
const inp = fs.createReadStream('input.txt');
const out = fs.createWriteStream('input.txt.gz');
inp.pipe(gzip).pipe(out);
Также возможно сжать или распаковать данные в одном шаге:
const input = '.................................';
zlib.deflate(input, (err, buffer) => {
if (!err) {
console.log(buffer.toString('base64'));
} else {
// handle error
}
});
const buffer = Buffer.from('eJzT0yMAAGTvBe8=', 'base64');
zlib.unzip(buffer, (err, buffer) => {
if (!err) {
console.log(buffer.toString());
} else {
// handle error
}
});
Использование пула потоков
Обратите внимание, что все API zlib, кроме тех, которые явно асинхронные, используют пул потоков libuv, что может иметь неожиданные и негативные последствия для производительности некоторых приложений. См. документацию UV_THREADPOOL_SIZE для получения дополнительной информации.
Сжатие HTTP-запросов и ответов
Модуль zlib может быть использован для реализации поддержки механизмов кодирования содержимого gzip и deflate , определенных в HTTP.
Заголовок HTTP Accept-Encoding используется в запросе HTTP для определения кодировок сжатия, принимаемых клиентом. Заголовок Content-Encoding используется для определения кодировок сжатия, фактически примененных к сообщению.
Примечание: приведенные ниже примеры сильно упрощены, чтобы продемонстрировать основную концепцию. Использование кодирования zlib может быть дорогостоящим, и результаты следует кэшировать. См. Настройка использования памяти для получения дополнительной информации о компромиссах между скоростью, памятью и сжатием при использовании zlib.
// client request example
const zlib = require('zlib');
const http = require('http');
const fs = require('fs');
const request = http.get({ host: 'example.com',
path: '/',
port: 80,
headers: { 'Accept-Encoding': 'gzip,deflate' } });
request.on('response', (response) => {
const output = fs.createWriteStream('example.com_index.html');
switch (response.headers['content-encoding']) {
// or, just use zlib.createUnzip() to handle both cases
case 'gzip':
response.pipe(zlib.createGunzip()).pipe(output);
break;
case 'deflate':
response.pipe(zlib.createInflate()).pipe(output);
break;
default:
response.pipe(output);
break;
}
});
// server example
// Running a gzip operation on every request is quite expensive.
// It would be much more efficient to cache the compressed buffer.
const zlib = require('zlib');
const http = require('http');
const fs = require('fs');
http.createServer((request, response) => {
const raw = fs.createReadStream('index.html');
let acceptEncoding = request.headers['accept-encoding'];
if (!acceptEncoding) {
acceptEncoding = '';
}
// Note: This is not a conformant accept-encoding parser.
// See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
if (/\bdeflate\b/.test(acceptEncoding)) {
response.writeHead(200, { 'Content-Encoding': 'deflate' });
raw.pipe(zlib.createDeflate()).pipe(response);
} else if (/\bgzip\b/.test(acceptEncoding)) {
response.writeHead(200, { 'Content-Encoding': 'gzip' });
raw.pipe(zlib.createGzip()).pipe(response);
} else {
response.writeHead(200, {});
raw.pipe(response);
}
}).listen(1337);
По умолчанию методы zlib будут выбрасывать ошибку при распаковке усечённых данных. Однако, если известно, что данные неполные, или требуется просмотреть только начало сжатого файла, можно подавить обработку ошибок по умолчанию, изменив метод сброса, используемый для распаковки последнего блока входных данных:
// This is a truncated version of the buffer from the above examples
const buffer = Buffer.from('eJzT0yMA', 'base64');
zlib.unzip(
buffer,
{ finishFlush: zlib.constants.Z_SYNC_FLUSH },
(err, buffer) => {
if (!err) {
console.log(buffer.toString());
} else {
// handle error
}
});
Это не изменит поведение в других ситуациях, вызывающих ошибки, например, когда входные данные имеют неверный формат. Используя этот метод, невозможно определить, закончились ли входные данные преждевременно или им не хватает контрольных сумм, что делает необходимым вручную проверить, что результат распаковки является корректным.
Настройка использования памяти
Из zlib/zconf.h, модифицировано для использования в node.js:
Требования к памяти для deflate (в байтах):
(1 << (windowBits + 2)) + (1 << (memLevel + 9))
То есть: 128 КБ для windowBits = 15 + 128 КБ для memLevel = 8 (значения по умолчанию) плюс несколько килобайт для небольших объектов.
Например, чтобы уменьшить значения памяти по умолчанию с 256 КБ до 128 КБ, параметры следует установить на:
const options = { windowBits: 14, memLevel: 7 };
Однако это, как правило, ухудшит сжатие.
Требования к памяти для inflate (в байтах) 1 << windowBits. То есть 32 КБ для windowBits = 15 (значение по умолчанию) плюс несколько килобайт для небольших объектов.
Это помимо одного внутреннего буфера вывода размером chunkSize, который по умолчанию равен 16 КБ.
Скорость сжатия zlib в наибольшей степени зависит от параметра level. Более высокое значение приведет к лучшему сжатию, но займет больше времени. Более низкое значение приведет к меньшему сжатию, но будет намного быстрее.
В целом, более высокие значения параметров использования памяти означают, что Node.js должен совершать меньше вызовов zlib, потому что он сможет обрабатывать больше данных в каждой операции write. Таким образом, это еще один фактор, влияющий на скорость, но с затратами на использование памяти.
Сброс
Вызов .flush() в потоке сжатия заставит zlib вернуть как можно больше выходных данных в данный момент. Это может произойти с затратами на качество сжатия, но может быть полезно, когда данные должны быть доступны как можно скорее.
В следующем примере flush() используется для записи сжатого частичного HTTP-ответа клиенту:
const zlib = require('zlib');
const http = require('http');
http.createServer((request, response) => {
// For the sake of simplicity, the Accept-Encoding checks are omitted.
response.writeHead(200, { 'content-encoding': 'gzip' });
const output = zlib.createGzip();
output.pipe(response);
setInterval(() => {
output.write(`The current time is ${Date()}\n`, () => {
// The data has been passed to zlib, but the compression algorithm may
// have decided to buffer the data for more efficient compression.
// Calling .flush() will make the data available as soon as the client
// is ready to receive it.
output.flush();
});
}, 1000);
}).listen(1337);
Константы
Все константы, определённые в zlib.h, также определены в require('zlib').constants. В обычном режиме работы использование этих констант не требуется. Они документированы, чтобы их присутствие не вызывало удивления. Этот раздел взят почти напрямую из документации zlib. Подробнее см. https://zlib.net/manual.html#Constants.
Примечание: Раньше константы были доступны непосредственно из require('zlib'), например, zlib.Z_NO_FLUSH. Доступ к константам напрямую из модуля по-прежнему возможен, но считается устаревшим.
Допустимые значения сброса.
zlib.constants.Z_NO_FLUSHzlib.constants.Z_PARTIAL_FLUSHzlib.constants.Z_SYNC_FLUSHzlib.constants.Z_FULL_FLUSHzlib.constants.Z_FINISHzlib.constants.Z_BLOCKzlib.constants.Z_TREES
Коды возврата для функций сжатия/распаковки. Отрицательные значения — ошибки, положительные значения используются для специальных, но обычных событий.
zlib.constants.Z_OKzlib.constants.Z_STREAM_ENDzlib.constants.Z_NEED_DICTzlib.constants.Z_ERRNOzlib.constants.Z_STREAM_ERRORzlib.constants.Z_DATA_ERRORzlib.constants.Z_MEM_ERRORzlib.constants.Z_BUF_ERRORzlib.constants.Z_VERSION_ERROR
Уровни сжатия.
zlib.constants.Z_NO_COMPRESSIONzlib.constants.Z_BEST_SPEEDzlib.constants.Z_BEST_COMPRESSIONzlib.constants.Z_DEFAULT_COMPRESSION
Стратегия сжатия.
zlib.constants.Z_FILTEREDzlib.constants.Z_HUFFMAN_ONLYzlib.constants.Z_RLEzlib.constants.Z_FIXEDzlib.constants.Z_DEFAULT_STRATEGY
Параметры класса
Каждый класс принимает объект options. Все параметры необязательны.
Обратите внимание, что некоторые параметры имеют отношение только к сжатию и игнорируются классами распаковки.
-
flush<целое> По умолчанию:zlib.constants.Z_NO_FLUSH -
finishFlush<целое> По умолчанию:zlib.constants.Z_FINISH -
chunkSize<целое> По умолчанию:16 * 1024 -
windowBits<целое> -
level<целое> (только для сжатия) -
memLevel<целое> (только для сжатия) -
strategy<целое> (только для сжатия) -
dictionary<Буфер> | <Массив типов> | <DataView> (только deflate/inflate, пустой словарь по умолчанию) -
info<логическое> (Еслиtrue, возвращает объект сbufferиengine)
См. описание deflateInit2 и inflateInit2 по адресу https://zlib.net/manual.html#Advanced для получения дополнительной информации.
Класс: zlib.Deflate
Сжимает данные с помощью deflate.
Класс: zlib.DeflateRaw
Сжимает данные с помощью deflate и не добавляет заголовок zlib.
Класс: zlib.Gunzip
Распаковывает gzip-поток.
Класс: zlib.Gzip
Сжимает данные с помощью gzip.
Класс: zlib.Inflate
Распаковывает deflate-поток.
Класс: zlib.InflateRaw
Распакуйте исходный поток deflate.
Класс: zlib.Unzip
Распакуйте сжатый Gzip или Deflate поток, автоматически определяя заголовок.
Класс: zlib.Zlib
Не экспортируется модулем zlib. Он документирован здесь, потому что является базовым классом для классов сжатия/распаковки.
zlib.bytesRead
Свойство zlib.bytesRead указывает количество байтов, прочитанных движком, прежде чем байты будут обработаны (сжаты или распакованы, в зависимости от производного класса).
zlib.close([callback])
Закрыть базовый дескриптор.
zlib.flush([kind], callback)
-
kindПо умолчанию:zlib.constants.Z_FULL_FLUSH
Очистить данные. Не используйте эту функцию без необходимости, преждевременное сброс негативно влияет на эффективность алгоритма сжатия.
Вызов этой функции только очищает внутреннее состояние zlib, и не выполняет сброс потоков. Вместо этого он ведет себя как обычный вызов .write(), т.е. он будет помещен в очередь за другими ожидающими записями и создаст выходные данные только при чтении данных из потока.
zlib.params(level, strategy, callback)
Динамически обновляет уровень сжатия и стратегию сжатия. Применимо только к алгоритму deflate.
zlib.reset()
Сбросить сжатие/распаковку до заводских настроек. Применимо только к алгоритмам inflate и deflate.
zlib.constants
Предоставляет объект, перечисляющий константы, связанные со Zlib.
zlib.createDeflate(options)
Создает и возвращает новый объект Deflate с заданными options.
zlib.createDeflateRaw(options)
Создает и возвращает новый объект DeflateRaw с заданными options.
Примечание: Обновление zlib с 1.2.8 до 1.2.11 изменило поведение при установке windowBits в 8 для потоков raw deflate. zlib автоматически устанавливал windowBits в 9, если он был изначально установлен в 8. Более новые версии zlib будут выбрасывать исключение, поэтому Node.js восстановил исходное поведение, увеличивая значение 8 до 9, так как передача windowBits = 9 в zlib фактически приводит к сжатому потоку, который эффективно использует 8-битное окно.
zlib.createGunzip(options)
Создает и возвращает новый объект Gunzip с заданными options.
zlib.createGzip(options)
Создает и возвращает новый объект Gzip с заданными options.
zlib.createInflate(options)
Создает и возвращает новый объект Inflate с заданными options.
zlib.createInflateRaw(options)
Создает и возвращает новый объект InflateRaw с заданными options.
zlib.createUnzip(options)
Создает и возвращает новый объект Unzip с заданными options.
Удобные методы
Все они принимают Buffer, TypedArray, DataView или строку в качестве первого аргумента, необязательный второй аргумент для передачи параметров в классы zlib и вызовет переданную функцию обратного вызова с callback(error, result).
Каждый метод имеет *Sync эквивалент, который принимает те же аргументы, но без обратного вызова.
zlib.deflate(buffer[, options], callback)
zlib.deflateSync(buffer[, options])
-
buffer<Буфер> | <TypedArray> | <DataView> | <строка>
Сжать фрагмент данных с помощью Deflate.
zlib.deflateRaw(buffer[, options], callback)
zlib.deflateRawSync(buffer[, options])
-
buffer<Буфер> | <TypedArray> | <DataView> | <строка>
Сжать фрагмент данных с помощью DeflateRaw.
zlib.gunzip(buffer[, options], callback)
zlib.gunzipSync(buffer[, options])
-
buffer<Буфер> | <TypedArray> | <DataView> | <строка>
Распаковать фрагмент данных с помощью Gunzip.
zlib.gzip(buffer[, options], callback)
END_OF_DOCUMENT_MARKERzlib.gzipSync(buffer[, options])
-
buffer<Buffer> | <TypedArray> | <DataView> | <string>
Сжать кусок данных с помощью Gzip.
zlib.inflate(buffer[, options], callback)
zlib.inflateSync(buffer[, options])
-
buffer<Buffer> | <TypedArray> | <DataView> | <string>
Разархивировать кусок данных с помощью Inflate.
zlib.inflateRaw(buffer[, options], callback)
zlib.inflateRawSync(buffer[, options])
-
buffer<Buffer> | <TypedArray> | <DataView> | <string>
Разархивировать кусок данных с помощью InflateRaw.
zlib.unzip(buffer[, options], callback)
zlib.unzipSync(buffer[, options])
-
buffer<Buffer> | <TypedArray> | <DataView> | <string>
Разархивировать кусок данных с помощью Unzip.
© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v8.x/docs/api/zlib.html