zip-lib
v1.3.1
Published
A zip and unzip library for Node.js.
Downloads
407,814
Maintainers
Readme
zip-lib
A zip and unzip library for Node.js with promise-based APIs, support for compressing to Buffer or extracting from Buffer, and advanced features like entry filtering, cancellation, and symlink-aware handling.
Install
npm install zip-libQuick Start
- Zip
- Unzip
- Advanced usage
- API
- Method: archiveFile
- Method: archiveFolder
- Method: extract
- Class: Zip
- Class: Unzip
- Options: IZipOptions
- Options: IExtractOptions
- Event: IEntryEvent
Zip
You can use zip-lib to compress files or folders.
Zip single file
import * as zl from "zip-lib";
async function zipToFile() {
try {
await zl.archiveFile("path/to/file.txt", "path/to/target.zip");
console.log("done");
} catch (error) {
console.error(error);
}
}
async function zipToBuffer() {
try {
const buffer = await zl.archiveFile("path/to/file.txt");
console.log("done", buffer.byteLength);
} catch (error) {
console.error(error);
}
}Zip single folder
import * as zl from "zip-lib";
async function zipToFile() {
try {
await zl.archiveFolder("path/to/folder", "path/to/target.zip");
console.log("done");
} catch (error) {
console.error(error);
}
}
async function zipToBuffer() {
try {
const buffer = await zl.archiveFolder("path/to/folder");
console.log("done", buffer.byteLength);
} catch (error) {
console.error(error);
}
}Unzip
import * as zl from "zip-lib";
async function unzipFromFile() {
try {
await zl.extract("path/to/target.zip", "path/to/target");
console.log("done");
} catch (error) {
console.error(error);
}
}
async function unzipFromBuffer(zipBuffer: Buffer) {
try {
await zl.extract(zipBuffer, "path/to/target");
console.log("done");
} catch (error) {
console.error(error);
}
}Advanced usage
Set the compression level
import * as zl from "zip-lib";
async function zipToFile() {
try {
await zl.archiveFolder("path/to/folder", "path/to/target.zip", {
compressionLevel: 9,
});
console.log("done");
} catch (error) {
console.error(error);
}
}Zip multiple files and folders
import * as zl from "zip-lib";
async function zipToFile() {
try {
const zip = new zl.Zip();
// Adds a file from the file system
zip.addFile("path/to/file.txt");
// Adds a folder from the file system, putting its contents at the root of the archive
zip.addFolder("path/to/folder");
// Generate the zip file.
await zip.archive("path/to/target.zip");
console.log("done");
} catch (error) {
console.error(error);
}
}The path/to/folder directory is as follows:
path/to/folder
.
├── dir1
│ ├── file.ext
├── dir2
└── file_in_root.extAnd the contents of the generated path/to/target.zip archive will be as follows:
path/to/target.zip
.
├── file.txt
├── dir1
│ ├── file.ext
├── dir2
└── file_in_root.extZip with metadata
import * as zl from "zip-lib";
async function zipToFile() {
try {
const zip = new zl.Zip();
// Adds a file from the file system
zip.addFile("path/to/file.txt", "renamedFile.txt");
zip.addFile("path/to/file2.txt", "folder/file.txt");
// Adds a folder from the file system and names it `new folder` within the archive
zip.addFolder("path/to/folder", "new folder");
// Generate the zip file.
zip.archive("path/to/target.zip");
console.log("done");
} catch (error) {
console.error(error);
}
}The path/to/folder directory is as follows:
path/to/folder
.
├── dir1
│ ├── file.ext
├── dir2
└── file_in_root.extAnd the contents of the generated path/to/target.zip archive will be as follows:
path/to/target.zip
.
├── renamedFile.txt
├── folder
│ ├── file.txt
├── new folder
├── dir1
│ ├── file.ext
├── dir2
└── file_in_root.extUnzip with entry callback
Using the onEntry callback, we can track extraction progress and control the extraction process. See IExtractOptions.
import * as zl from "zip-lib";
async function unzipFromFile() {
try {
const unzip = new zl.Unzip({
// Called before an item is extracted.
onEntry: (event) => {
console.log(event.entryCount, event.entryName);
},
});
await unzip.extract("path/to/target.zip", "path/to/target");
console.log("done");
} catch (error) {
console.error(error);
}
}Unzip and exclude specified entries
The following code shows how to exclude the __MACOSX folder in the zip file when extracting. See IExtractOptions.
import * as zl from "zip-lib";
async function unzipFromFile() {
try {
const unzip = new zl.Unzip({
// Called before an item is extracted.
onEntry: (event) => {
if (/^__MACOSX\//.test(event.entryName)) {
// entry name starts with __MACOSX/
event.preventDefault();
}
},
});
await unzip.extract("path/to/target.zip", "path/to/target");
console.log("done");
} catch (error) {
console.error(error);
}
}Cancel zip
If the cancel method is called after the archive is complete, nothing will happen.
import * as zl from "zip-lib";
const zip = new zl.Zip();
async function zipToFile() {
try {
zip.addFile("path/to/file.txt");
await zip.archive("path/to/target.zip");
console.log("done");
} catch (error) {
if (error instanceof Error && error.name === "Canceled") {
console.log("cancel");
} else {
console.log(error);
}
}
}
function cancel() {
zip.cancel();
}Cancel unzip
If the cancel method is called after the extract is complete, nothing will happen.
import * as zl from "zip-lib";
const unzip = new zl.Unzip();
async function unzipFromFile() {
try {
await unzip.extract("path/to/target.zip", "path/to/target");
console.log("done");
} catch (error) {
if (error instanceof Error && error.name === "Canceled") {
console.log("cancel");
} else {
console.log(error);
}
}
}
function cancel() {
unzip.cancel();
}API
Choose the API based on how much control you need:
- Use
archiveFile,archiveFolder, andextractfor simple one-shot operations. - Use
Zipwhen you need to add multiple files or folders, rename entries, or cancel compression. - Use
Unzipwhen you need to filter entries withonEntryor cancel extraction.
Method: archiveFile
Compress a single file.
archiveFile(file: string, options?: IZipOptions): Promise<Buffer>
archiveFile(file: string, zipFile: string, options?: IZipOptions): Promise<void>file: Path to the source file.zipFile: Optional output zip file path.options: Optional IZipOptions.
If zipFile is provided, the archive is written to disk and the method returns Promise<void>. Otherwise it returns the generated zip as a Buffer.
Method: archiveFolder
Compress all contents of a folder.
archiveFolder(folder: string, options?: IZipOptions): Promise<Buffer>
archiveFolder(folder: string, zipFile: string, options?: IZipOptions): Promise<void>folder: Path to the source folder.zipFile: Optional output zip file path.options: Optional IZipOptions.
If zipFile is provided, the archive is written to disk and the method returns Promise<void>. Otherwise it returns the generated zip as a Buffer.
Method: extract
Extract a zip file or zip buffer to a target folder.
extract(zipFile: string, targetFolder: string, options?: IExtractOptions): Promise<void>
extract(zipBuffer: Buffer, targetFolder: string, options?: IExtractOptions): Promise<void>zipFile: Path to a zip file on disk.zipBuffer: A zip archive in memory.targetFolder: Destination folder.options: Optional IExtractOptions.
Class: Zip
Build an archive incrementally when the top-level helpers are not enough.
Constructor
new Zip(options?: IZipOptions)options: Optional IZipOptions.
Methods
addFile(file: string, metadataPath?: string): void
addFolder(folder: string, metadataPath?: string): void
archive(): Promise<Buffer>
archive(zipFile: string): Promise<void>
cancel(): voidaddFile: Adds one file to the archive.addFolder: Adds one folder to the archive.metadataPath: Optional path stored inside the zip. A validmetadataPathmust not start with/or/[A-Za-z]:\//, and must not contain...archive(): Returns the zip as aBuffer.archive(zipFile): Writes the zip directly to disk.cancel(): Cancels compression. Calling it after completion has no effect.
Use metadataPath to rename files or folders inside the archive. It is typically computed with path.relative(root, realPath).
Class: Unzip
Extract with entry filtering and cancellation support.
Constructor
new Unzip(options?: IExtractOptions)options: Optional IExtractOptions.
Methods
extract(zipFile: string, targetFolder: string): Promise<void>
extract(zipBuffer: Buffer, targetFolder: string): Promise<void>
cancel(): voidextract(...): Extracts from a zip file path or aBuffer.cancel(): Cancels extraction. Calling it after completion has no effect.
Options: IZipOptions
interface IZipOptions {
followSymlinks?: boolean;
compressionLevel?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
}followSymlinks: Defaultfalse. Iftrue, adds the target of a symbolic link. Iffalse, adds the symbolic link itself.compressionLevel: Default6. Use0to store file data without compression, or1-9to deflate file data.
Options: IExtractOptions
interface IExtractOptions {
overwrite?: boolean;
safeSymlinksOnly?: boolean;
symlinkAsFileOnWindows?: boolean;
onEntry?: (event: IEntryEvent) => void;
}overwrite: Defaultfalse. Iftrue, deletes the target directory before extraction.safeSymlinksOnly: Defaultfalse. Iftrue, refuses to create symlinks whose targets are outside the extraction root.symlinkAsFileOnWindows: Defaulttrue. On Windows, iftrue, symbolic links are extracted as regular files. Iffalse, the library tries to create real symbolic links instead. This may fail withEPERMwhen the current process is not allowed to create symlinks. Keep the default for better compatibility; set this tofalseonly if you want to preserve symlinks as symlinks.onEntry: Called before an entry is extracted. Use it to inspect or skip entries.
WARNING: On Windows, creating symbolic links may require administrator privileges, depending on system policy. If Windows Developer Mode is enabled, non-administrator processes can usually create symlinks as well. If
symlinkAsFileOnWindowsisfalseand the current process is not allowed to create symlinks, extraction may fail withEPERM.
Event: IEntryEvent
interface IEntryEvent {
readonly entryName: string;
readonly entryCount: number;
preventDefault(): void;
}entryName: The current entry name.entryCount: The total number of entries in the archive.preventDefault(): Skips the current entry.
License
Licensed under the MIT license.
