Cómo trabajar con archivos zip en Node.js

El autor seleccionó Open Sourcing Mental Illness para recibir una donación como parte del programa Write for DOnations .
Introducción
Trabajar con archivos es una de las tareas más habituales entre los desarrolladores. A medida que los archivos aumentan de tamaño, comienzan a ocupar un espacio significativo en el disco duro. Tarde o temprano, es posible que deba transferir los archivos a otros servidores o cargar varios archivos desde su máquina local a diferentes plataformas. Algunas de estas plataformas tienen límites de tamaño de archivo y no aceptan archivos grandes. Para solucionar esto, puede agrupar los archivos en un solo archivo ZIP. Un archivo ZIP es un formato de archivo que empaqueta y comprime archivos con el algoritmo de compresión sin pérdida . El algoritmo puede reconstruir los datos sin ninguna pérdida de datos. En Node.js , puede usar el adm-zip
módulo para crear y leer archivos ZIP.
En este tutorial, utilizará adm-zip
el módulo para comprimir, leer y descomprimir archivos. Primero, combinará varios archivos en un archivo ZIP utilizando adm-zip
. Luego, enumerará el contenido del archivo ZIP. Después de eso, agregará un archivo a un archivo ZIP existente y, finalmente, extraerá un archivo ZIP en un directorio.
Prerrequisitos
Para seguir este tutorial, necesitarás:
-
Node.js instalado en su entorno local o de servidor. Siga Cómo instalar Node.js y crear un entorno de desarrollo local para instalar Node.js.
-
Conocimiento de cómo escribir un programa Node.js, consulte Cómo escribir y ejecutar su primer programa en Node.js.
-
Un conocimiento básico de la programación asincrónica en JavaScript. Visite nuestro tutorial Comprensión del bucle de eventos, las devoluciones de llamadas, las promesas y Async/Await en JavaScript para aprender los conceptos básicos.
-
Conocimiento de cómo trabajar con archivos en Node.js. Consulta el tutorial Cómo trabajar con archivos usando el módulo fs en Node.js para repasar cómo trabajar con archivos.
Paso 1: Configuración del proyecto
En este paso, creará el directorio para su proyecto y lo instalará adm-zip
como una dependencia. Este directorio es donde guardará los archivos de programa. También creará otro directorio que contenga archivos de texto y una imagen. Archivará este directorio en la siguiente sección.
Crea un directorio llamado zip_app
con el siguiente comando:
- mkdir zip_app
Navegue hasta el directorio recién creado con el cd
comando:
- cd zip_app
Dentro del directorio, crea un package.json
archivo para administrar las dependencias del proyecto:
- npm init -y
La -y
opción crea un package.json
archivo predeterminado.
A continuación, instale adm-zip
con el npm install
comando:
- npm install adm-zip
Después de ejecutar el comando, npm
se instalará adm-zip
y actualizará el package.json
archivo.
A continuación, crea un directorio llamado test
y muévete a él:
- mkdir test cd test
En este directorio, creará tres archivos de texto y descargará una imagen. Los tres archivos se rellenarán con contenido ficticio para aumentar su tamaño. Esto ayudará a demostrar la compresión ZIP cuando archive este directorio.
Crea un archivo file1.txt
y rellénalo con contenido ficticio utilizando el siguiente comando:
- yes "dummy content" | head -n 100000 file1.txt
El yes
comando registra la cadena dummy content
repetidamente. Con el comando pipe |
, envía la salida del yes
comando para que se use como entrada para el head
comando. El head
comando imprime parte de la entrada dada en la salida estándar. La -n
opción especifica la cantidad de líneas que se deben escribir en la salida estándar. Finalmente, redirige la head
salida a un nuevo archivo file1.txt
usando .
Cree un segundo archivo con la cadena “contenido ficticio” repetida 300.000 líneas:
- yes "dummy content" | head -n 300000 file2.txt
Crea otro archivo con la dummy content
cadena repetida 600.000 líneas:
- yes "dummy content" | head -n 600000 file3.txt
Por último, descargue una imagen en el directorio usando curl
:
- curl -O https://assets.digitalocean.com/how-to-process-images-in-node-js-with-sharp/underwater.png
Regrese al directorio principal del proyecto con el siguiente comando:
- cd ..
Te moverá ..
al directorio principal, que es zip_app
.
Ya ha creado el directorio del proyecto, ha instalado adm-zip
y ha creado un directorio con archivos para archivar. En el siguiente paso, archivará un directorio utilizando el adm-zip
módulo.
Paso 2: creación de un archivo ZIP
En este paso, utilizarás adm-zip
para comprimir y archivar el directorio que creaste en la sección anterior.
Para archivar el directorio, deberá importar el adm-zip
módulo y utilizar el addLocalFolder()
método del módulo para agregar el directorio al adm-zip
objeto ZIP del módulo. Luego, utilizará el writeZip()
método del módulo para guardar el archivo en su sistema local.
Cree y abra un nuevo archivo createArchive.js
en su editor de texto preferido. Este tutorial utiliza nano
, un editor de texto de línea de comandos:
- nano createArchive.js
A continuación, solicita en el adm-zip
módulo de tu createArchive.js
archivo:
zip_app/createArchive.js
const AdmZip = require("adm-zip");
El adm-zip
módulo proporciona una clase que contiene métodos para crear archivos ZIP.
Dado que es habitual encontrar archivos grandes durante el proceso de archivado, es posible que acabes bloqueando el hilo principal hasta que se guarde el archivo ZIP. Para escribir código sin bloqueo, definirás una función asincrónica para crear y guardar un archivo ZIP.
En su createArchive.js
archivo, agregue el siguiente código resaltado:
zip_app/createArchive.js
const AdmZip = require("adm-zip");async function createZipArchive() { const zip = new AdmZip(); const outputFile = "test.zip"; zip.addLocalFolder("./test"); zip.writeZip(outputFile); console.log(`Created ${outputFile} successfully`);}createZipArchive();
createZipArchive
es una función asincrónica que crea un archivo ZIP a partir de un directorio determinado. Lo que la hace asincrónica es la async
palabra clave que definió antes de la etiqueta de la función. Dentro de la función, crea una instancia del adm-zip
módulo, que proporciona métodos que puede usar para leer y crear archivos. Cuando crea una instancia, adm-zip
crea un ZIP en memoria donde puede agregar archivos o directorios.
A continuación, se define el nombre del archivo y se almacena en la outputDir
variable. Para agregar el test
directorio al archivo en memoria, se invoca el addLocalFolder()
método from adm-zip
con la ruta del directorio como argumento.
Una vez que se agrega el directorio, se invoca el writeZip()
método from adm-zip
con una variable que contiene el nombre del archivo ZIP. El writeZip()
método guarda el archivo en el disco local.
Una vez hecho esto, invoca console.log()
para registrar que el archivo ZIP se ha creado correctamente.
Finalmente, llama a la createZipArchive()
función.
Antes de ejecutar el archivo, envuelva el código en un bloque try…catch para manejar errores de tiempo de ejecución:
zip_app/createArchive.js
const AdmZip = require("adm-zip");async function createZipArchive() { try { const zip = new AdmZip(); const outputFile = "test.zip"; zip.addLocalFolder("./test"); zip.writeZip(outputFile); console.log(`Created ${outputFile} successfully`); } catch (e) { console.log(`Something went wrong. ${e}`); }}createZipArchive();
Dentro del try
bloque, el código intentará crear un archivo ZIP. Si tiene éxito, la createZipArchive()
función saldrá y se saltará el catch
bloque. Si la creación de un archivo ZIP genera un error, la ejecución saltará al catch
bloque y registrará el error en la consola.
Guarde y salga del archivo nano
con CTRL+X
. Presione Enter y
para guardar los cambios y confirme el archivo presionando ENTER
en Windows o la RETURN
tecla en Mac.
Ejecute el createArchive.js
archivo usando el node
comando:
- node createArchive.js
Recibirás el siguiente resultado:
OutputCreated test.zip successfully
Enumere el contenido del directorio para ver si se ha creado el archivo ZIP:
- ls
Recibirá la siguiente salida que muestra el archivo entre los contenidos:
OutputcreateArchive.js node_modules package-lock.jsonpackage.json test test.zip
Con la confirmación de que se ha creado el archivo ZIP, comparará el archivo ZIP y el test
tamaño del archivo del directorio para ver si la compresión funciona.
Compruebe el test
tamaño del directorio usando el du
comando:
- du -h test
La -h
bandera indica du
que se debe mostrar el tamaño del directorio en un formato legible para humanos.
Después de ejecutar el comando, recibirá el siguiente resultado:
Output15Mtest
A continuación, compruebe el test.zip
tamaño del archivo comprimido:
- du -h test.zip
El du
comando registra la siguiente salida:
Output760Ktest.zip
Como puede ver, al crear el archivo ZIP, el tamaño del directorio se redujo de 15 megabytes (MB) a 760 kilobytes (KB), lo que supone una gran diferencia. El archivo ZIP es más portátil y de menor tamaño.
Ahora que ha creado un archivo ZIP, está listo para enumerar el contenido en un archivo ZIP.
Paso 3: Listado de archivos en un archivo ZIP
En este paso, leerá y listará todos los archivos en un archivo ZIP usando adm-zip
. Para ello, creará una instancia del adm-zip
módulo con la ruta de su archivo ZIP. Luego, llamará al getEntries()
método del módulo que devuelve una matriz de objetos. Cada objeto contiene información importante sobre un elemento en el archivo ZIP. Para listar los archivos, iterará sobre la matriz y accederá al nombre de archivo desde el objeto y lo registrará en la consola.
Crea y abre readArchive.js
en tu editor de texto favorito:
- nano readArchive.js
En su readArchive.js
, agregue el siguiente código para leer y enumerar el contenido de un archivo ZIP:
zip_app/readArchive.js
const AdmZip = require("adm-zip");async function readZipArchive(filepath) { try { const zip = new AdmZip(filepath); for (const zipEntry of zip.getEntries()) { console.log(zipEntry.toString()); } } catch (e) { console.log(`Something went wrong. ${e}`); }}readZipArchive("./test.zip");
Primero, necesitas estar en el adm-zip
módulo.
A continuación, se define la readZipArchive()
función, que es una función asincrónica. Dentro de la función, se crea una instancia de adm-zip
con la ruta del archivo ZIP que se desea leer. La ruta del archivo se proporciona mediante el filepath
parámetro. adm-zip
leerá el archivo y lo analizará.
Después de leer el archivo, se define una for....of
declaración que itera sobre los objetos de una matriz que el getEntries()
método adm-zip
devuelve cuando se invoca. En cada iteración, el objeto se asigna a la zipEntry
variable. Dentro del bucle, se convierte el objeto en una cadena que representa el objeto mediante el toString()
método Node.js y, luego, se registra en la consola mediante el console.log()
método.
Finalmente, invoca la readZipArchive()
función con la ruta del archivo ZIP como argumento.
Guarde y salga de su archivo, luego ejecute el archivo con el siguiente comando:
- node readArchive.js
Obtendrá un resultado similar al siguiente (editado para abreviar):
Output{"entryName": "file1.txt","name": "file1.txt","comment": "","isDirectory": false,"header": {...},"compressedData": "27547 bytes buffer","data": "null"}...
La consola registrará cuatro objetos. Los demás objetos se han eliminado para que el tutorial sea breve.
Cada archivo del archivo se representa con un objeto similar al que se muestra en la salida anterior. Para obtener el nombre de archivo de cada archivo, debe acceder a la name
propiedad.
En su readArchive.js
archivo, agregue el siguiente código resaltado para acceder a cada nombre de archivo:
zip_app/readArchive.js
const AdmZip = require("adm-zip");async function readZipArchive(filepath) { try { const zip = new AdmZip(filepath); for (const zipEntry of zip.getEntries()) { console.log(zipEntry.name); } } catch (e) { console.log(`Something went wrong. ${e}`); }}readZipArchive("./test.zip");
Guarde y salga del editor de texto. Ahora, vuelva a ejecutar el archivo con el node
comando:
- node readArchive.js
Al ejecutar el archivo se obtiene el siguiente resultado:
Outputfile1.txtfile2.txtfile3.txtunderwater.png
La salida ahora registra el nombre de archivo de cada archivo en el archivo ZIP.
Ahora puede leer y enumerar cada archivo en un archivo ZIP. En la siguiente sección, agregará un archivo a un archivo ZIP existente.
Paso 4: Agregar un archivo a un archivo existente
En este paso, creará un archivo y lo agregará al archivo ZIP que creó anteriormente sin extraerlo. Primero, leerá el archivo ZIP creando una adm-zip
instancia. En segundo lugar, invocará el addFile()
método del módulo para agregar el archivo al ZIP. Por último, guardará el archivo ZIP en el sistema local.
Crea otro archivo file4.txt
con contenido ficticio repetido 600.000 líneas:
- yes "dummy content" | head -n 600000 file4.txt
Crea y abre updateArchive.js
en tu editor de texto:
- nano updateArchive.js
Requerir en el adm-zip
módulo y el fs
módulo que le permite trabajar con archivos en su updateArchive.js
archivo:
const AdmZip = require("adm-zip");const fs = require("fs").promises;
Necesita la versión basada en promesas del fs
módulo, que le permite escribir código asincrónico. Cuando invoca un fs
método, devolverá una promesa.
A continuación, en su updateArchive.js
archivo, agregue el siguiente código resaltado para agregar un nuevo archivo al archivo ZIP:
zip_app/updateArchive.js
const AdmZip = require("adm-zip");const fs = require("fs").promises;async function updateZipArchive(filepath) { try { const zip = new AdmZip(filepath); content = await fs.readFile("./file4.txt"); zip.addFile("file4.txt", content); zip.writeZip(filepath); console.log(`Updated ${filepath} successfully`); } catch (e) { console.log(`Something went wrong. ${e}`); }}updateZipArchive("./test.zip");
updateZipArchive
es una función asincrónica que lee un archivo en el sistema de archivos y lo agrega a un ZIP existente. En la función, se crea una instancia de adm-zip
con la ruta del archivo ZIP como filepath
parámetro. A continuación, se invoca el método fs
del módulo readFile()
para leer el archivo en el sistema de archivos. El readFile()
método devuelve una promesa, que se resuelve con la await
palabra clave ( await
es válida solo en funciones asincrónicas). Una vez resuelta, el método devuelve un objeto de búfer , que contiene el contenido del archivo.
A continuación, invoca el addFile()
método from adm-zip
. El método acepta dos argumentos. El primer argumento es el nombre del archivo que deseas agregar al archivo y el segundo argumento es el objeto de búfer que contiene el contenido del archivo que readFile()
lee el método.
Luego, invoca el método adm-zip
del módulo writeZip()
para guardar y escribir los cambios nuevos en el archivo ZIP. Una vez hecho esto, llama al console.log()
método para registrar un mensaje de éxito.
Finalmente, invoca la updateZipArchive()
función con la ruta del archivo Zip como argumento.
Guarde y salga del archivo. Ejecute el updateArchive.js
archivo con el siguiente comando:
- node updateArchive.js
Verás un resultado como este:
OutputUpdated ./test.zip successfully
Ahora, confirme que el archivo ZIP contiene el nuevo archivo. Ejecute el readArchive.js
archivo para enumerar el contenido del archivo ZIP con el siguiente comando:
- node readArchive.js
Recibirás el siguiente resultado:
file1.txtfile2.txtfile3.txtfile4.txtunderwater.png
Esto confirma que el archivo se ha agregado al ZIP.
Ahora que puedes agregar un archivo a un archivo existente, extraerás el archivo en la siguiente sección.
Paso 5: extracción de un archivo zip
En este paso, leerá y extraerá todo el contenido de un archivo ZIP en un directorio. Para extraer un archivo ZIP, deberá crear una instancia adm-zip
con la ruta del archivo. Después, invocará el extractAllTo()
método del módulo con el nombre del directorio en el que desea que residan los contenidos ZIP extraídos.
Crea y abre extractArchive.js
en tu editor de texto:
- nano extractArchive.js
Requerir en el adm-zip
módulo y el path
módulo en su extractArchive.js
archivo:
zip_app/extractArchive.js
const AdmZip = require("adm-zip");const path = require("path");
El path
módulo proporciona métodos útiles para tratar con rutas de archivos.
Aún en su extractArchive.js
archivo, agregue el siguiente código resaltado para extraer un archivo:
zip_app/extractArchive.js
const AdmZip = require("adm-zip");const path = require("path");async function extractArchive(filepath) { try { const zip = new AdmZip(filepath); const outputDir = `${path.parse(filepath).name}_extracted`; zip.extractAllTo(outputDir); console.log(`Extracted to "${outputDir}" successfully`); } catch (e) { console.log(`Something went wrong. ${e}`); }}extractArchive("./test.zip");
extractArchive()
es una función asincrónica que toma un parámetro que contiene la ruta del archivo ZIP. Dentro de la función, se crea una instancia adm-zip
con la ruta del archivo ZIP proporcionada por el filepath
parámetro.
A continuación, se define un literal de plantilla . Dentro del marcador de posición del literal de plantilla ( ${}
), se invoca el parse()
método desde el path
módulo con la ruta del archivo. El parse()
método devuelve un objeto. Para obtener el nombre del archivo ZIP sin la extensión del archivo, se añade la name
propiedad al objeto que parse()
devuelve el método. Una vez que se devuelve el nombre del archivo, el literal de plantilla interpola el valor con la _extracted
cadena. Luego, el valor se almacena en la outputDir
variable. Este será el nombre del directorio extraído.
A continuación, invoca el método adm-zip
del módulo extractAllTo
con el nombre del directorio almacenado outputDir
para extraer el contenido del directorio. Después de eso, invoca console.log()
para registrar un mensaje de éxito.
Finalmente, llama a la extractArchive()
función con la ruta del archivo ZIP.
Guarde el archivo y salga del editor, luego ejecute el extractArchive.js
archivo con el siguiente comando:
- node extractArchive.js
Recibirá el siguiente resultado:
OutputExtracted to "test_extracted" successfully
Confirme que se ha creado el directorio que contiene el contenido ZIP:
- ls
Recibirá el siguiente resultado:
OutputcreateArchive.js file4.txt package-lock.jsonreadArchive.js test.zip updateArchive.jsextractArchive.js node_modules package.jsontest test_extracted
Ahora, navegue hasta el directorio que contiene el contenido extraído:
- cd test_extracted
Enumere el contenido del directorio:
- ls
Recibirá el siguiente resultado:
Outputfile1.txt file2.txt file3.txt file4.txt underwater.png
Ahora puedes ver que el directorio tiene todos los archivos que estaban en el directorio original.
Ahora ha extraído el contenido del archivo ZIP en un directorio.
Conclusión
En este tutorial, creaste un archivo ZIP, enumeraste su contenido, agregaste un nuevo archivo al archivo y extrajiste todo su contenido en un directorio usando adm-zip
module. Esto servirá como una buena base para trabajar con archivos ZIP en Node.js.
Para obtener más información sobre adm-zip
el módulo, consulte la documentación de adm-zip . Para seguir desarrollando su conocimiento sobre Node.js, consulte la serie Cómo codificar en Node.js
Deja una respuesta