Maison  >  Article  >  interface Web  >  Utiliser Node.js pour implémenter des fonctions de compression et de décompression

Utiliser Node.js pour implémenter des fonctions de compression et de décompression

亚连
亚连original
2018-06-06 09:27:073737parcourir

Cet article présente principalement la méthode de compression et de décompression basée sur Node.js. Maintenant, je la partage avec vous et la donne comme référence.

Formats de compression

zip et gzip sont les deux formats de compression les plus courants que nous voyons. Bien sûr, gzip est rarement exposé à Windows.

tar est un format d'archive qui ne se compresse pas par défaut. Il doit être combiné avec gzip pour compresser le fichier tar final en un fichier tar.gz au format gzip, qui est généralement abrégé en tgz.

Pourquoi rar n'est-il pas mentionné ? Puisqu'il s'agit d'un algorithme protégé par un brevet, vous pouvez obtenir l'outil de décompression gratuitement, tandis que l'outil de compression doit être payant. Par conséquent, dans nos scénarios d’application généraux, les fichiers compressés rar sont rarement fournis.

Cet article présentera respectivement comment compresser et décompresser gzip, tar, tgz et zip sous Node.js.

Bibliothèque de fichiers non compressés

La bibliothèque de fichiers non compressés utilisée dans cet article provient de urllib Vous devez d'abord la cloner et accéder au répertoire spécifié.

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

gzip

sous Linux dans le monde, les responsabilités de chaque outil seront très pures et très uniques. Par exemple, gzip ne compressera que les fichiers. Quant à la façon dont le dossier est emballé et compressé, cela n'a rien à voir avec cela. .

Ligne de commande gzip pour compresser un fichier

Par exemple, si nous voulons gzip le fichier nodejs-compressing-demo/lib/urllib.js, nous obtiendrons un fichier urllib.js .gz, le fichier source sera supprimé.

$ 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

Taille du fichier réduite de 31318 octets à 8909 octets, soit plus de 3,5 fois l'effet de compression.

Vous pouvez également compresser et enregistrer le fichier sous n'importe quel fichier via la méthode pipe, combinée avec la commande cat :

$ 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 implémente gzip

Bien sûr, nous n'implémenterons pas vraiment un algorithme et un outil gzip à partir de zéro. Dans le monde de Node.js, ces bibliothèques de base ont déjà été préparées pour vous, il nous suffit de les utiliser directement.

Cet article utilisera le module de compression pour implémenter tous les codes de compression et de décompression.

Pourquoi choisir la compression ? Parce qu'il offre des garanties suffisantes de qualité de code et de tests unitaires, est dans un état de maintenance active, dispose d'une API très conviviale et prend également en charge les interfaces de streaming.

Interface de promesse

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);
 });

Combiné avec le modèle de programmation asynchrone/attente, le code peut être écrit comme une opération io asynchrone ordinaire.

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();

Interface Stream

Il est important de noter que lors de la programmation en mode Stream, vous devez gérer l'événement d'erreur de chaque flux et détruire manuellement tous les flux .

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);

Selon la recommandation officielle de contre-pression dans les flux, nous devrions utiliser le module de pompe pour coopérer avec la programmation du mode Stream et laisser la pompe terminer le travail de nettoyage de ces flux.

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');
 }
});

Avantages de l'interface Stream

L'interface Stream semble bien plus compliquée que l'interface Promise. Pourquoi existe-t-il un tel scénario d'application ?

En fait, dans le domaine des services HTTP, le modèle Stream aura de plus grands avantages, car la requête HTTP elle-même est un Request Stream. Si vous souhaitez renvoyer un fichier téléchargé avec une compression gzip, vous n'en avez pas besoin. pour enregistrer le fichier téléchargé à l'aide de l'interface Stream sur le disque local, mais consommer ce flux de fichiers directement.

En utilisant l'exemple de code pour le téléchargement du fichier egg, nous pouvons implémenter la compression gzip et revenir avec une légère modification.

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());
 }
}

tar | gzip > tgz

gzip Chapitre Vous pouvez savoir à l'avance que tar est responsable de l'empaquetage du dossier.

Par exemple, si vous souhaitez regrouper l'intégralité du dossier nodejs-compressing-dem o dans un fichier et l'envoyer à d'autres, vous pouvez utiliser la commande tar.

$ 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

Comme vous pouvez le constater, le fichier packagé par tar est généralement plus volumineux car il n'est pas compressé et sa taille est proche de la taille totale réelle du dossier. Nous allons donc tous compresser en même temps que l'emballage.

$ 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

La différence de taille entre tar et tgz est plus de 5 fois, ce qui peut réduire considérablement la bande passante de transmission du réseau.

Node.js implémente tgz

Interface de promesse

Utilisez d'abord compressing.tar.compressDir(sourceDir, targetFile) pour Emballez un dossier dans un fichier tar, puis utilisez la méthode de compression gzip ci-dessus pour compresser le fichier tar dans un fichier tgz.

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);
 });

Combiné au modèle de programmation async/await, le code sera plus facile à lire :

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();

Interface Stream

Par compression La classe .tar.Stream peut ajouter dynamiquement n'importe quel fichier et dossier à un objet de flux tar, ce qui est très flexible.

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 peut en fait être considéré comme une combinaison "commerciale" de tar + gzip. Il permet aux utilisateurs de ne pas faire la distinction entre les fichiers compressés et les fichiers compressés. . dossier, utilisez simplement mon zip quand même.

Un exemple d'utilisation de l'outil de ligne de commande zip pour compresser un dossier :

$ 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

En comparant les tailles de fichiers de tgz et zip, on peut voir que sous les paramètres de compression par défaut, gzip est plus efficace que zip good.

Node.js implémente zip

Le code d'implémentation est similaire à tar, sauf qu'il est compressé par défaut et qu'il n'est pas nécessaire d'ajouter le processus 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);
 });

Résumé

La compression et la décompression basées sur Node.js sont-elles plus faciles qu'on ne l'imaginait ? Grâce au géant npm, nous pouvons avoir l'expérience simple de programmer avec des outils en ligne de commande.

Qu'il s'agisse de l'interface Promise ou de l'interface Stream, elle a son scénario le plus adapté La choisirez-vous ?

À ce stade, avec les capacités de compression et de décompression dont vous disposez, quels types de services et de fonctions pouvez-vous proposer ?

Ce qui précède est ce que j'ai compilé pour vous. J'espère que cela vous sera utile à l'avenir.

Articles connexes :

Utilisation de tween.js pour implémenter l'algorithme d'animation interpolation

Expliquez les références dans React en détail (tutoriel détaillé)

Comment obtenir un effet de défilement de cycle intermittent de texte via JS

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn