Create, read and edit .zip files with JavaScript in both browser and Node.js environments
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Load and parse existing ZIP files from various input sources with validation, error handling, and customizable parsing options. Supports multiple input formats and provides comprehensive ZIP structure analysis.
Load ZIP data using the static method to create a new JSZip instance.
/**
* Load ZIP data and create new JSZip instance (static method)
* @param content - ZIP data in various formats
* @param options - Loading options for parsing behavior
* @returns Promise resolving to new JSZip instance
*/
static loadAsync(content: InputFileFormat, options?: JSZipLoadOptions): Promise<JSZip>;Usage Examples:
import JSZip from "jszip";
// Load from file input (browser)
const fileInput = document.getElementById('zipFile');
const file = fileInput.files[0];
const zip = await JSZip.loadAsync(file);
// Load from URL fetch (browser/Node.js)
const response = await fetch('https://example.com/archive.zip');
const arrayBuffer = await response.arrayBuffer();
const zip = await JSZip.loadAsync(arrayBuffer);
// Load from Node.js Buffer
import fs from 'fs';
const buffer = fs.readFileSync('archive.zip');
const zip = await JSZip.loadAsync(buffer);
// Load from Base64 string
const base64Data = "UEsDBAoAAAAAAIdYzlQAAA..."; // Base64 ZIP data
const zip = await JSZip.loadAsync(base64Data, {base64: true});
// Load with options
const zip = await JSZip.loadAsync(zipData, {
checkCRC32: true,
createFolders: true
});Load ZIP data into an existing JSZip instance.
/**
* Load ZIP data into existing JSZip instance
* @param data - ZIP data in various formats
* @param options - Loading options for parsing behavior
* @returns Promise resolving to the same JSZip instance
*/
loadAsync(data: InputFileFormat, options?: JSZipLoadOptions): Promise<JSZip>;Usage Examples:
const zip = new JSZip();
// Add some initial files
zip.file("readme.txt", "Initial content");
// Load additional ZIP data into the same instance
await zip.loadAsync(additionalZipData);
// The instance now contains both initial files and loaded files
console.log(Object.keys(zip.files)); // Shows all files
// Load with custom options
await zip.loadAsync(zipBuffer, {
checkCRC32: false, // Skip CRC validation for speed
createFolders: false // Don't create folder entries
});Various data formats that can be loaded as ZIP files.
type InputFileFormat = InputByType[keyof InputByType] | Promise<InputByType[keyof InputByType]>;
interface InputByType {
base64: string;
string: string;
text: string;
binarystring: string;
array: number[];
uint8array: Uint8Array;
arraybuffer: ArrayBuffer;
blob: Blob;
stream: NodeJS.ReadableStream;
}Usage Examples:
// String formats
const zipFromBase64 = await JSZip.loadAsync(base64String, {base64: true});
const zipFromBinary = await JSZip.loadAsync(binaryString);
// Binary formats
const zipFromArray = await JSZip.loadAsync(numberArray);
const zipFromUint8 = await JSZip.loadAsync(uint8Array);
const zipFromBuffer = await JSZip.loadAsync(arrayBuffer);
// Browser-specific
const zipFromBlob = await JSZip.loadAsync(blob);
// Node.js-specific
const zipFromStream = await JSZip.loadAsync(readableStream);
// Async input (Promise-wrapped)
const zipFromPromise = await JSZip.loadAsync(
fetch('archive.zip').then(r => r.arrayBuffer())
);Configure ZIP parsing behavior and validation settings.
interface JSZipLoadOptions {
/** Set to true if input data is base64 encoded */
base64?: boolean;
/** Enable CRC32 checksum validation */
checkCRC32?: boolean;
/** Set to true for optimized binary string parsing */
optimizedBinaryString?: boolean;
/** Automatically create folder entries for file paths */
createFolders?: boolean;
/** Custom filename decoding function */
decodeFileName?: (bytes: string[] | Uint8Array | Buffer) => string;
}Usage Examples:
// Basic loading with validation
const zipWithValidation = await JSZip.loadAsync(zipData, {
checkCRC32: true // Validate file integrity
});
// Loading base64 data
const zipFromBase64 = await JSZip.loadAsync(base64String, {
base64: true
});
// Custom filename handling for non-UTF8 filenames
const zipWithCustomNames = await JSZip.loadAsync(zipData, {
decodeFileName: (bytes) => {
// Handle special encoding like CP437 or Shift-JIS
return customDecode(bytes);
}
});
// Performance-optimized loading
const zipFast = await JSZip.loadAsync(zipData, {
checkCRC32: false, // Skip CRC validation
createFolders: false, // Don't create folder objects
optimizedBinaryString: true
});
// Complete loading with all options
const zipComplete = await JSZip.loadAsync(zipData, {
base64: false,
checkCRC32: true,
createFolders: true,
optimizedBinaryString: false,
decodeFileName: (bytes) => {
// Convert bytes to UTF-8 string
return new TextDecoder('utf-8').decode(new Uint8Array(bytes));
}
});Work with the loaded ZIP structure and access file contents.
Usage Examples:
// Load a ZIP file
const zip = await JSZip.loadAsync(zipData);
// Inspect the loaded structure
console.log("Files in ZIP:", Object.keys(zip.files));
// Check if specific files exist
if (zip.file("config.json")) {
const config = await zip.file("config.json").async("string");
console.log("Config:", JSON.parse(config));
}
// List all files and folders
zip.forEach((relativePath, file) => {
console.log(`${file.dir ? 'Folder' : 'File'}: ${relativePath}`);
console.log(` Date: ${file.date}`);
console.log(` Size: ${file._data ? file._data.uncompressedSize : 'unknown'}`);
});
// Extract all text files
const textFiles = zip.filter((relativePath, file) => {
return !file.dir && relativePath.endsWith('.txt');
});
for (const file of textFiles) {
const content = await file.async("string");
console.log(`Content of ${file.name}:`, content);
}
// Access file metadata
const someFile = zip.file("document.pdf");
if (someFile) {
console.log("File info:", {
name: someFile.name,
size: someFile._data?.uncompressedSize,
date: someFile.date,
comment: someFile.comment,
compression: someFile.options.compression
});
}Handle various loading errors and validation failures.
Usage Examples:
try {
const zip = await JSZip.loadAsync(suspiciousData, {
checkCRC32: true
});
console.log("ZIP loaded successfully");
} catch (error) {
if (error.message.includes("CRC32")) {
console.error("ZIP file is corrupted (CRC mismatch)");
} else if (error.message.includes("signature")) {
console.error("Invalid ZIP file format");
} else if (error.message.includes("Zip64")) {
console.error("ZIP64 format not supported");
} else {
console.error("Unknown ZIP loading error:", error.message);
}
}
// Handle specific file extraction errors
try {
const zip = await JSZip.loadAsync(zipData);
const file = zip.file("protected.txt");
if (file) {
const content = await file.async("string");
}
} catch (error) {
if (error.message.includes("password")) {
console.error("File is password protected");
} else if (error.message.includes("compression")) {
console.error("Unsupported compression method");
} else {
console.error("File extraction error:", error.message);
}
}Handle security-related concerns when loading ZIP files.
Usage Examples:
// Check for zip-slip attacks
const zip = await JSZip.loadAsync(untrustedZipData);
zip.forEach((relativePath, file) => {
// Check for directory traversal
if (relativePath.includes('../') || relativePath.startsWith('/')) {
console.warn(`Suspicious path detected: ${relativePath}`);
return; // Skip this file
}
// Check original filename for traversal attempts
if (file.unsafeOriginalName && file.unsafeOriginalName !== relativePath) {
console.warn(`Path traversal attempt: ${file.unsafeOriginalName} -> ${relativePath}`);
}
});
// Limit extraction based on size
const MAX_EXTRACTED_SIZE = 100 * 1024 * 1024; // 100MB
let totalSize = 0;
for (const [path, file] of Object.entries(zip.files)) {
if (!file.dir) {
const size = file._data?.uncompressedSize || 0;
totalSize += size;
if (totalSize > MAX_EXTRACTED_SIZE) {
throw new Error("ZIP file too large to extract safely");
}
}
}
// Validate filenames
const SAFE_FILENAME_REGEX = /^[a-zA-Z0-9._\-\/]+$/;
zip.forEach((relativePath, file) => {
if (!SAFE_FILENAME_REGEX.test(relativePath)) {
console.warn(`Unsafe filename: ${relativePath}`);
}
});