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
Extract file contents from ZIP archives in various formats with support for streaming, progress tracking, and platform-specific optimizations. Provides access to individual file data within loaded ZIP files.
Extract file content in various output formats asynchronously.
/**
* Extract file content in specified format
* @param type - Output format type
* @param onUpdate - Optional progress callback
* @returns Promise resolving to file content in specified format
*/
async<T extends OutputType>(type: T, onUpdate?: OnUpdateCallback): Promise<OutputByType[T]>;Usage Examples:
import JSZip from "jszip";
// Load a ZIP file
const zip = await JSZip.loadAsync(zipData);
// Extract text content
const textFile = zip.file("readme.txt");
if (textFile) {
const content = await textFile.async("string");
console.log("Text content:", content);
}
// Extract binary content
const imageFile = zip.file("photo.jpg");
if (imageFile) {
const arrayBuffer = await imageFile.async("arraybuffer");
const uint8Array = await imageFile.async("uint8array");
const blob = await imageFile.async("blob");
}
// Extract with progress tracking
const largeFile = zip.file("large-video.mp4");
if (largeFile) {
const content = await largeFile.async("arraybuffer", (metadata) => {
console.log(`Extracting: ${metadata.percent}%`);
if (metadata.currentFile) {
console.log(`Processing: ${metadata.currentFile}`);
}
});
}
// Extract different formats
const dataFile = zip.file("data.bin");
if (dataFile) {
const base64 = await dataFile.async("base64");
const binaryString = await dataFile.async("binarystring");
const numberArray = await dataFile.async("array");
const nodeBuffer = await dataFile.async("nodebuffer"); // Node.js only
}Extract file content as a Node.js ReadableStream for efficient processing of large files.
/**
* Extract file content as Node.js ReadableStream
* @param type - Stream type (defaults to 'nodebuffer')
* @param onUpdate - Optional progress callback
* @returns Node.js ReadableStream containing file data
*/
nodeStream(type?: 'nodebuffer', onUpdate?: OnUpdateCallback): NodeJS.ReadableStream;Usage Examples:
import JSZip from "jszip";
import fs from "fs";
// Load ZIP file
const zip = await JSZip.loadAsync(fs.readFileSync('archive.zip'));
// Extract large file as stream
const videoFile = zip.file("presentation.mp4");
if (videoFile) {
const stream = videoFile.nodeStream('nodebuffer');
// Pipe to output file
stream.pipe(fs.createWriteStream('extracted-video.mp4'));
// Handle stream events
stream.on('data', (chunk) => {
console.log(`Received ${chunk.length} bytes`);
});
stream.on('end', () => {
console.log('File extraction completed');
});
stream.on('error', (error) => {
console.error('Extraction error:', error);
});
}
// Extract with progress tracking
const documentFile = zip.file("large-document.pdf");
if (documentFile) {
const stream = documentFile.nodeStream('nodebuffer', (metadata) => {
console.log(`Extraction progress: ${metadata.percent}%`);
});
stream.pipe(fs.createWriteStream('extracted-document.pdf'));
}Access metadata and properties of individual files within the ZIP archive.
interface JSZipObject {
/** Absolute path of the file within the ZIP */
name: string;
/** Original filename from ZIP (may contain path traversal) */
unsafeOriginalName?: string;
/** Whether this entry is a directory */
dir: boolean;
/** Last modification date */
date: Date;
/** File comment */
comment: string;
/** UNIX file permissions */
unixPermissions: number | string | null;
/** DOS file permissions */
dosPermissions: number | null;
/** File options including compression settings */
options: JSZipObjectOptions;
}
interface JSZipObjectOptions {
/** Compression method used for this file */
compression: Compression;
}Usage Examples:
const zip = await JSZip.loadAsync(zipData);
// Inspect file properties
const file = zip.file("document.txt");
if (file) {
console.log("File metadata:", {
name: file.name,
isDirectory: file.dir,
lastModified: file.date,
comment: file.comment,
compression: file.options.compression,
unixPermissions: file.unixPermissions,
dosPermissions: file.dosPermissions
});
// Check for security issues
if (file.unsafeOriginalName) {
console.warn(`Original name: ${file.unsafeOriginalName}`);
console.warn(`Sanitized name: ${file.name}`);
}
}
// List all files with metadata
zip.forEach((relativePath, file) => {
if (!file.dir) {
console.log(`File: ${file.name}`);
console.log(` Size: ${file._data?.uncompressedSize || 'unknown'}`);
console.log(` Compressed: ${file._data?.compressedSize || 'unknown'}`);
console.log(` Compression: ${file.options.compression}`);
console.log(` Modified: ${file.date.toISOString()}`);
if (file.comment) {
console.log(` Comment: ${file.comment}`);
}
}
});Various formats for extracting file content.
type OutputType = keyof OutputByType;
interface OutputByType {
base64: string;
string: string;
text: string;
binarystring: string;
array: number[];
uint8array: Uint8Array;
arraybuffer: ArrayBuffer;
blob: Blob;
nodebuffer: Buffer;
}Usage Examples:
const zip = await JSZip.loadAsync(zipData);
const file = zip.file("example.bin");
if (file) {
// Text formats
const base64String = await file.async("base64");
const textString = await file.async("string");
const binaryString = await file.async("binarystring");
// Binary formats
const uint8Array = await file.async("uint8array");
const arrayBuffer = await file.async("arraybuffer");
const numberArray = await file.async("array");
// Platform-specific formats
const blob = await file.async("blob"); // Browser
const buffer = await file.async("nodebuffer"); // Node.js
}
// Choose format based on file type
const textFile = zip.file("readme.txt");
const imageFile = zip.file("photo.png");
const dataFile = zip.file("binary.dat");
if (textFile) {
const text = await textFile.async("string");
console.log("Text content:", text);
}
if (imageFile) {
// For images, use blob in browser or buffer in Node.js
const imageBlob = await imageFile.async("blob");
const imageUrl = URL.createObjectURL(imageBlob);
}
if (dataFile) {
// For binary data, use ArrayBuffer or Uint8Array
const binaryData = await dataFile.async("uint8array");
processBinaryData(binaryData);
}Monitor file extraction progress with detailed metadata.
interface JSZipMetadata {
/** Completion percentage (0-100) */
percent: number;
/** Currently processing file path */
currentFile: string | null;
}
type OnUpdateCallback = (metadata: JSZipMetadata) => void;Usage Examples:
const zip = await JSZip.loadAsync(zipData);
const largeFile = zip.file("huge-dataset.csv");
if (largeFile) {
// Extract with progress tracking
const content = await largeFile.async("string", (metadata) => {
// Update UI progress bar
updateProgressBar(metadata.percent);
// Show current status
console.log(`Extracting: ${metadata.percent}%`);
if (metadata.currentFile) {
console.log(`Processing: ${metadata.currentFile}`);
}
// Handle completion
if (metadata.percent === 100) {
console.log("Extraction completed!");
}
});
console.log("Final content length:", content.length);
}
// Progress tracking with streaming
const videoFile = zip.file("presentation.mp4");
if (videoFile) {
const stream = videoFile.nodeStream('nodebuffer', (metadata) => {
document.getElementById('status').textContent =
`Extracting: ${metadata.percent}% - ${metadata.currentFile || 'Processing...'}`;
});
stream.pipe(fs.createWriteStream('output.mp4'));
}Extract multiple files efficiently with various strategies.
Usage Examples:
const zip = await JSZip.loadAsync(zipData);
// Extract all text files
const textFiles = zip.filter((relativePath, file) => {
return !file.dir && (relativePath.endsWith('.txt') || relativePath.endsWith('.md'));
});
const extractedTexts = {};
for (const file of textFiles) {
extractedTexts[file.name] = await file.async("string");
}
// Extract all images as blobs (browser)
const imageFiles = zip.filter((relativePath, file) => {
return !file.dir && /\.(png|jpg|jpeg|gif)$/i.test(relativePath);
});
const extractedImages = {};
for (const file of imageFiles) {
extractedImages[file.name] = await file.async("blob");
}
// Parallel extraction with Promise.all
const allFiles = zip.filter((relativePath, file) => !file.dir);
const fileContents = await Promise.all(
allFiles.map(async (file) => ({
name: file.name,
content: await file.async("uint8array"),
metadata: {
date: file.date,
size: file._data?.uncompressedSize,
compression: file.options.compression
}
}))
);
// Extract with size limits
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
const safeFiles = zip.filter((relativePath, file) => {
const size = file._data?.uncompressedSize || 0;
return !file.dir && size <= MAX_FILE_SIZE;
});
const safeExtractions = {};
for (const file of safeFiles) {
safeExtractions[file.name] = await file.async("string");
}Handle extraction errors and validation failures.
Usage Examples:
const zip = await JSZip.loadAsync(zipData);
// Handle missing files
const file = zip.file("might-not-exist.txt");
if (file) {
try {
const content = await file.async("string");
console.log("Content:", content);
} catch (error) {
console.error("Extraction failed:", error.message);
}
} else {
console.log("File not found in ZIP");
}
// Handle corrupted files
try {
const suspiciousFile = zip.file("suspicious.bin");
if (suspiciousFile) {
const content = await suspiciousFile.async("uint8array");
console.log("Extracted successfully");
}
} catch (error) {
if (error.message.includes("CRC32")) {
console.error("File is corrupted (CRC mismatch)");
} else if (error.message.includes("compression")) {
console.error("Unsupported compression method");
} else {
console.error("Unknown extraction error:", error.message);
}
}
// Robust extraction with fallbacks
async function safeExtractText(zip, filename) {
const file = zip.file(filename);
if (!file) {
return null;
}
try {
return await file.async("string");
} catch (error) {
console.warn(`Failed to extract ${filename} as text:`, error.message);
try {
// Try binary extraction as fallback
const binary = await file.async("uint8array");
return new TextDecoder('utf-8', { fatal: false }).decode(binary);
} catch (fallbackError) {
console.error(`Complete extraction failure for ${filename}:`, fallbackError.message);
return null;
}
}
}