Heim  >  Artikel  >  Web-Frontend  >  Node.js implementiert Komprimierung und Dekomprimierung

Node.js implementiert Komprimierung und Dekomprimierung

小云云
小云云Original
2018-02-22 09:46:032245Durchsuche

Komprimierungsformate

zip und gzip sind die beiden häufigsten Komprimierungsformate, die wir sehen. Natürlich wird gzip unter Windows selten verfügbar gemacht. Tar ist ein Archivformat, das standardmäßig nicht komprimiert wird. Es muss mit gzip kombiniert werden, um die endgültige TAR-Datei in eine tar.gz-Datei im gzip-Format zu komprimieren, das normalerweise mit tgz abgekürzt wird.

Warum wird rar nicht erwähnt? Da es sich um einen patentgeschützten Algorithmus handelt, können Sie das Dekomprimierungstool kostenlos erhalten, während das Komprimierungstool kostenpflichtig ist. Daher werden in unseren allgemeinen Anwendungsszenarien selten komprimierte RAR-Dateien bereitgestellt.

In diesem Artikel wird erläutert, wie gzip, tar, tgz und zip unter Node.js komprimiert bzw. dekomprimiert werden.

Unkomprimierte Dateibibliothek

Die in diesem Artikel verwendete unkomprimierte Dateibibliothek stammt von urllib. Sie müssen sie zuerst klonen und in das angegebene Verzeichnis wechseln.

git clone https://github.com/node-modules/urllib.git nodejs-compressing-demo

gzip

In der Linux-Welt werden die Verantwortlichkeiten jedes Tools sehr klar und sehr einzeln sein, wie zum Beispiel gzip, das nur Dateien komprimiert. Die Art und Weise, wie der Ordner verpackt und komprimiert wird, hat nichts damit zu tun. Dafür ist tar verantwortlich.

gzip-Befehlszeile zum Komprimieren einer Datei

Wenn wir beispielsweise die Datei nodejs-compressing-demo/lib/urllib.js gzipen möchten, erhalten wir eine urllib.js .gz-Datei, die Quelldatei wird gelöscht.


$ ls -l nodejs-compressing-demo/lib/urllib.js
-rw-r--r-- 1 a a 31318 Feb 12 11:27 nodejs-compressing-demo/lib/urllib.js

$ gzip nodejs-compressing-demo/lib/urllib.js

$ ls -l nodejs-compressing-demo/lib/urllib.js.gz
-rw-r--r-- 1 a a 8909 Feb 12 11:27 nodejs-compressing-demo/lib/urllib.js.gz

# 还原压缩文件
$ gunzip nodejs-compressing-demo/lib/urllib.js.gz

Die Dateigröße wird von 31318 Byte auf 8909 Byte reduziert, mehr als das 3,5-fache des Komprimierungseffekts.

Sie können auch die Pipe-Methode in Kombination mit dem Befehl cat verwenden, um die Datei zu komprimieren und als beliebige Datei zu speichern:


$ ls -l nodejs-compressing-demo/README.md
-rw-r--r-- 1 a a 13747 Feb 12 11:27 nodejs-compressing-demo/README.md

$ cat nodejs-compressing-demo/README.md | gzip > README.md.gz

$ ls -l README.md.gz
-rw-r--r-- 1 a a 4903 Feb 12 11:50 README.md.gz

Node.js-Implementierung gzip

Natürlich werden wir keinen gzip-Algorithmus und ein Tool von Grund auf implementieren. In der Welt von Node.js wurden diese grundlegenden Bibliotheken bereits für Sie vorbereitet Sie müssen nur die Box öffnen.

In diesem Artikel wird das Komprimierungsmodul verwendet, um alle Komprimierungs- und Dekomprimierungscodes zu implementieren.

Warum Komprimierung wählen? Weil es über ausreichende Codequalität und Unit-Testing-Garantien verfügt, sich in einem aktiven Wartungszustand befindet, über eine sehr benutzerfreundliche API verfügt und auch Streaming-Schnittstellen unterstützt.

Promise-Schnittstelle


const compressing = require('compressing');

// 选择 gzip 格式,然后调用 compressFile 方法
compressing.gzip.compressFile('nodejs-compressing-demo/lib/urllib.js', 'nodejs-compressing-demo/lib/urllib.js.gz')
 .then(() => {
  console.log('success');
 })
 .catch(err => {
  console.error(err);
 });

// 解压缩是反响过程,接口都统一为 uncompress
compressing.gzip.uncompress('nodejs-compressing-demo/lib/urllib.js.gz', 'nodejs-compressing-demo/lib/urllib.js2')
 .then(() => {
  console.log('success');
 })
 .catch(err => {
  console.error(err);
 });

In Kombination mit dem Async/Await-Programmiermodell wird der Code als gewöhnliches asynchrones IO geschrieben Betrieb.


const compressing = require('compressing');

async function main() {
 try {
  await compressing.gzip.compressFile('nodejs-compressing-demo/lib/urllib.js',
   'nodejs-compressing-demo/lib/urllib.js.gz');
  console.log('success');
 } catch (err) {
  console.error(err);
 }

 // 解压缩
 try {
  await compressing.gzip.uncompress('nodejs-compressing-demo/lib/urllib.js.gz',
   'nodejs-compressing-demo/lib/urllib.js2');
  console.log('success');
 } catch (err) {
  console.error(err);
 }
}

main();

Stream-Schnittstelle

Es ist wichtig zu beachten, dass Sie beim Programmieren im Stream-Modus mit den Fehlern umgehen müssen jedes Streams, und alle Streams müssen manuell zerstört werden.


fs.createReadStream('nodejs-compressing-demo/lib/urllib.js')
 .on('error', handleError)
 .pipe(new compressing.gzip.FileStream()) // It's a transform stream
 .on('error', handleError)
 .pipe(fs.createWriteStream('nodejs-compressing-demo/lib/urllib.js.gz2'))
 .on('error', handleError);

// 解压缩,就是 pipe 的方向倒转过来
fs.createReadStream('nodejs-compressing-demo/lib/urllib.js.gz2')
 .on('error', handleError)
 .pipe(new compressing.gzip.UncompressStream()) // It's a transform stream
 .on('error', handleError)
 .pipe(fs.createWriteStream('nodejs-compressing-demo/lib/urllib.js3'))
 .on('error', handleError);

Gemäß der offiziellen Empfehlung für „Backpressuring in Streams“ sollten wir das Pumpenmodul verwenden, um mit der Stream-Modus-Programmierung zusammenzuarbeiten, und die Pumpe die Reinigungsarbeit dieser Streams abschließen lassen .


const pump = require('pump');

const source = fs.createReadStream('nodejs-compressing-demo/lib/urllib.js');
const target = fs.createWriteStream('nodejs-compressing-demo/lib/urllib.js.gz2');

pump(source, new compressing.gzip.FileStream(), target, err => {
 if (err) {
  console.error(err);
 } else {
  console.log('success');
 }
});

// 解压缩
pump(fs.createReadStream('nodejs-compressing-demo/lib/urllib.js.gz2'),
  new compressing.gzip.FileStream(),
  fs.createWriteStream('nodejs-compressing-demo/lib/urllib.js3'),
  err => {
 if (err) {
  console.error(err);
 } else {
  console.log('success');
 }
});

Vorteile der Stream-Schnittstelle

Die Stream-Schnittstelle scheint viel komplizierter zu sein als die Promise-Schnittstelle, warum gibt es das? So etwas? Wie sieht es mit Anwendungsszenarien aus?

Tatsächlich bietet das Stream-Modell im Bereich der HTTP-Dienste größere Vorteile, da die HTTP-Anfrage selbst ein Request Stream ist. Wenn Sie eine hochgeladene Datei mit GZIP-Komprimierung zurückgeben möchten, ist dies nicht erforderlich um die hochgeladene Datei über die Stream-Schnittstelle auf der lokalen Festplatte zu speichern, diesen Dateistream jedoch direkt zu konsumieren.

Mit dem Beispielcode für das Hochladen von Eierdateien können wir die GZIP-Komprimierung implementieren und mit einer geringfügigen Änderung zurückgeben.


const pump = require('pump');

class UploadFormController extends Controller {
 // ... other codes

 async upload() {
  const stream = await this.ctx.getFileStream();
  // 直接将压缩流赋值给 ctx.body,实现边压缩边返回的流式响应
  this.ctx.body = pump(stream, new compressing.gzip.FileStream());
 }
}

gzip > tgz

gzip-Kapitel Sie können im Voraus wissen, dass tar für die Verpackung verantwortlich ist Ordner :Paket:.

Wenn Sie beispielsweise den gesamten Ordner nodejs-compressing-dem o in eine Datei packen und an andere senden möchten, können Sie den Befehl tar verwenden.


$ tar -c -f nodejs-compressing-demo.tar nodejs-compressing-demo/

$ ls -l nodejs-compressing-demo.tar
-rw-r--r-- 1 a a 206336 Feb 12 14:01 nodejs-compressing-demo.tar

Wie Sie sehen können, ist die von tar gepackte Datei im Allgemeinen größer, da sie unkomprimiert ist und die Größe nahe an der tatsächlichen Gesamtgröße des Ordners liegt. Deshalb werden wir alle gleichzeitig mit dem Verpacken komprimieren.


$ tar -c -z -f nodejs-compressing-demo.tgz nodejs-compressing-demo/

$ ls -l nodejs-compressing-demo.tgz
-rw-r--r-- 1 a a 39808 Feb 12 14:07 nodejs-compressing-demo.tgz

Der Größenunterschied zwischen tar und tgz beträgt mehr als das Fünffache, was die Netzwerkübertragungsbandbreite erheblich reduzieren kann.

Node.js implementiert tgz

Promise-Schnittstelle

Verwenden Sie zunächst compressing.tar.compressDir(sourceDir, targetFile) für Packen Sie einen Ordner in eine TAR-Datei und komprimieren Sie die TAR-Datei dann mit der oben genannten gzip-Komprimierungsmethode in eine TGZ-Datei.


const compressing = require('compressing');

compressing.tar.compressDir('nodejs-compressing-demo', 'nodejs-compressing-demo.tar')
 .then(() => {
  return compressing.gzip.compressFile('nodejs-compressing-demo.tar',
   'nodejs-compressing-demo.tgz');
 });
 .then(() => {
  console.log('success');
 })
 .catch(err => {
  console.error(err);
 });

// 解压缩
compressing.gzip.uncompress('nodejs-compressing-demo.tgz', 'nodejs-compressing-demo.tar')
 .then(() => {
  return compressing.tar.uncompress('nodejs-compressing-demo.tar',
   'nodejs-compressing-demo2');
 });
 .then(() => {
  console.log('success');
 })
 .catch(err => {
  console.error(err);
 });

In Kombination mit dem Async/Wait-Programmiermodell wird der Code einfacher zu lesen:


const compressing = require('compressing');

async function main() {
 try {
  await compressing.tar.compressDir('nodejs-compressing-demo',
   'nodejs-compressing-demo.tar');
  await compressing.gzip.compressFile('nodejs-compressing-demo.tar',
   'nodejs-compressing-demo.tgz');
  console.log('success');
 } catch (err) {
  console.error(err);
 }
 
 // 解压缩
 try {
  await compressing.gzip.uncompress('nodejs-compressing-demo.tgz',
   'nodejs-compressing-demo.tar');
  await compressing.tar.uncompress('nodejs-compressing-demo.tar',
   'nodejs-compressing-demo2');
  console.log('success');
 } catch (err) {
  console.error(err);
 }
}

main();

Stream-Schnittstelle

Über die Klasse compressing.tar.Stream können Sie beliebige Dateien und Ordner dynamisch zu einem TAR-Stream-Objekt hinzufügen, was sehr flexibel ist.


const tarStream = new compressing.tar.Stream();
// dir
tarStream.addEntry('dir/path/to/compress');
// file
tarStream.addEntry('file/path/to/compress');
// buffer
tarStream.addEntry(buffer);
// stream
tarStream.addEntry(stream);

const destStream = fs.createWriteStream('path/to/destination.tgz');
pump(tarStream, new compressing.gzip.FileStream(), destStream, err => {
 if (err) {
  console.error(err);
 } else {
  console.log('success');
 }
});

zip

zip kann tatsächlich als eine „kommerzielle“ Kombination aus tar + gzip angesehen werden, die das ermöglicht Leser müssen nicht unterscheiden, ob es sich um eine komprimierte Datei oder einen komprimierten Ordner handelt. Verwenden Sie trotzdem einfach meine ZIP-Datei.

Beispiel für die Verwendung des Zip-Befehlszeilentools zum Komprimieren eines Ordners:


$ zip -r nodejs-compressing-demo.zip nodejs-compressing-demo/
 adding: nodejs-compressing-demo/ (stored 0%)
 adding: nodejs-compressing-demo/test/ (stored 0%)
 ...
 adding: nodejs-compressing-demo/.travis.yml (deflated 36%)

$ ls -l nodejs-compressing-demo.*
-rw-r--r-- 1 a a 206336 Feb 12 14:06 nodejs-compressing-demo.tar
-rw-r--r-- 1 a a  39808 Feb 12 14:07 nodejs-compressing-demo.tgz
-rw-r--r-- 1 a a  55484 Feb 12 14:34 nodejs-compressing-demo.zip

Durch den Vergleich der Dateigrößen von tgz und zip können Sie sehen Die Standardkomprimierung Unter den Parametern ist die Wirkung von gzip besser als die von zip.

Node.js-Implementierungs-Zip

实现代码跟 tar 类似,只不过默认是压缩的,不需要再添加 gzip 的过程。


const compressing = require('compressing');

compressing.zip.compressDir('nodejs-compressing-demo', 'nodejs-compressing-demo.zip')
 .then(() => {
  console.log('success');
 })
 .catch(err => {
  console.error(err);
 });

// 解压缩
compressing.zip.uncompress('nodejs-compressing-demo.zip', 'nodejs-compressing-demo3')
 .then(() => {
  console.log('success');
 })
 .catch(err => {
  console.error(err);
 });

总结

基于 Node.js 实现的压缩和解压缩是否比想象中简单?感谢 npm 这个巨人,让我们编程也能拥有命令行工具那样简单的体验。

无论是 Promise 接口,还是 Stream 接口,都有它最合适的场景,你会选择了吗?

到此,你拥有的压缩和解压缩能力,你能够做什么样的服务和功能呢?

相关推荐:

Grunt针对静态文件的压缩,版本控制打包详解

微信小程序图片压缩功能的实现方法

php解压zip压缩包到指定目录实现方法


Das obige ist der detaillierte Inhalt vonNode.js implementiert Komprimierung und Dekomprimierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn