DEV Community

eimza
eimza

Posted on

Parsing ZIP Archives in the Browser with JSZip: A Practical Guide

Most developers reach for server-side tools when they need to work with ZIP files. But what if your users are uploading sensitive documents (legal filings, medical records, financial data) and you can't — or shouldn't — send them to a server?

Here's how to parse ZIP archives entirely in the browser using JSZip.

Setup

<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
Enter fullscreen mode Exit fullscreen mode

Or for offline use, bundle jszip.min.js locally (~100KB gzipped).

Reading a File Input

const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', async (e) => {
    const file = e.target.files[0];
    const arrayBuffer = await file.arrayBuffer();

    const zip = await JSZip.loadAsync(arrayBuffer);

    // List all entries
    zip.forEach((relativePath, zipEntry) => {
        console.log(relativePath, zipEntry.dir ? '📁' : '📄');
    });
});
Enter fullscreen mode Exit fullscreen mode

Extracting Text Files

const contentXml = zip.file("content.xml");
if (contentXml) {
    const text = await contentXml.async("string"); // UTF-8 text
    console.log(text);
}
Enter fullscreen mode Exit fullscreen mode

Extracting Binary Files as Base64

for (const [path, entry] of Object.entries(zip.files)) {
    if (path.match(/\.(png|jpg|jpeg)$/i)) {
        const base64 = await entry.async("base64");
        const img = document.createElement("img");
        img.src = `data:image/png;base64,${base64}`;
        document.body.appendChild(img);
    }
}
Enter fullscreen mode Exit fullscreen mode

Creating ZIP Files

const zip = new JSZip();
zip.file("content.xml", '<template format_id="1.8">...</template>');
zip.file("images/logo.png", base64Data, { base64: true });

const blob = await zip.generateAsync({
    type: "blob",
    compression: "DEFLATE",
    compressionOptions: { level: 6 }
});

// Trigger download
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "document.udf";
a.click();
Enter fullscreen mode Exit fullscreen mode

Performance Considerations

File Size Parse Time (M1 Mac, Chrome)
50 KB ~5ms
1 MB ~25ms
10 MB ~180ms
50 MB ~900ms

For files >10MB, consider using zip.generateAsync() with a progress callback:

const blob = await zip.generateAsync({ type: "blob" }, (metadata) => {
    console.log(`Progress: ${metadata.percent.toFixed(1)}%`);
});
Enter fullscreen mode Exit fullscreen mode

Real-World Use Case: udf2md

We used this approach in udf2md to convert Turkey's UYAP court documents (.udf) to Markdown — entirely in the browser. Zero backend, full GDPR/KVKK compliance.

The key insight: if you never send data to a server, you never have a data breach.

Top comments (0)