ZIP-Archive im Browser mit JSZip erstellen
ZIP-Archive direkt im Browser zu erstellen kann die Nutzererfahrung deutlich verbessern, weil die serverseitige Komprimierung entfällt. In diesem DevTip zeigen wir, wie Sie mit JSZip und der HTML5 File API Nutzern ermöglichen, mehrere Dateien auszuwählen, per Drag-and-drop abzulegen und vollständig clientseitig in einem ZIP-Archiv zu bündeln.
Vorteile der clientseitigen ZIP-Erzeugung
Das Erzeugen von ZIP-Dateien im Browser bietet mehrere Vorteile:
- Geringere Serverlast: Keine serverseitige Verarbeitung nötig.
- Bessere Nutzererfahrung: Sofortiges Feedback und schnellere Downloads.
- Mehr Datenschutz: Dateien verlassen das Gerät der Nutzer nie.
Überblick über JSZip und die HTML5 File API
JSZip ist eine JavaScript-Bibliothek, mit der Sie ZIP-Dateien direkt im Browser erstellen, lesen und bearbeiten können. Version 3.10.1 bietet eine API für den Umgang mit ZIP-Archiven. In Kombination mit der HTML5 File API ermöglicht sie eine nahtlose clientseitige Dateiverarbeitung.
Installation
Sie können JSZip auf mehrere Arten installieren:
# Using npm
npm install jszip
# Using yarn
yarn add jszip
Alternativ binden Sie es über ein CDN ein:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
Dateieingabe und Drag-and-drop einrichten
Beginnen wir mit einer einfachen HTML-Struktur:
<label for="fileInput">Choose files for the ZIP archive</label>
<input type="file" id="fileInput" multiple />
<div id="dropZone">Drag and drop files here</div>
<button id="zipButton">Create ZIP</button>
<div id="progress"></div>
Fügen Sie etwas grundlegendes JavaScript hinzu, um die Dateiauswahl zu verarbeiten:
const fileInput = document.getElementById('fileInput')
const dropZone = document.getElementById('dropZone')
let selectedFiles = []
fileInput.addEventListener('change', (event) => {
selectedFiles = Array.from(event.target.files)
})
dropZone.addEventListener('dragover', (event) => {
event.preventDefault()
dropZone.classList.add('active')
})
dropZone.addEventListener('dragleave', () => {
dropZone.classList.remove('active')
})
dropZone.addEventListener('drop', (event) => {
event.preventDefault()
dropZone.classList.remove('active')
selectedFiles = Array.from(event.dataTransfer.files)
})
Dateien asynchron mit FileReader lesen
Wenn Sie die Bytes einer Datei selbst untersuchen möchten, verwenden Sie FileReader mit
Fehlerbehandlung. JSZip nimmt auch direkt File entgegen, wie es das
Archivbeispiel weiter unten tut:
function readFileAsync(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = () =>
resolve({
name: file.name,
data: reader.result,
})
reader.onerror = () => reject(reader.error)
reader.readAsArrayBuffer(file)
})
}
Dateien in JSZip integrieren
Integrieren wir die Dateien nun in eine JSZip-Instanz und erzeugen das ZIP-Archiv mit Fortschrittsverfolgung:
async function createZip(files) {
const progressElement = document.getElementById('progress')
const zip = new JSZip()
// Check file size limits
const totalSize = files.reduce((sum, file) => sum + file.size, 0)
if (totalSize > 100 * 1024 * 1024) {
// 100MB limit
alert('Total file size exceeds 100MB limit')
return
}
// Add files to zip
const names = new Set()
for (const file of files) {
if (names.has(file.name)) {
progressElement.textContent = `Duplicate filename: ${file.name}. Rename it before archiving.`
return
}
names.add(file.name)
zip.file(file.name, file)
progressElement.textContent = `Added ${file.name} to archive`
}
// Generate and download the zip
try {
progressElement.textContent = 'Generating ZIP file...'
const content = await zip.generateAsync(
{
type: 'blob',
compression: 'DEFLATE',
compressionOptions: { level: 6 },
},
(metadata) => {
progressElement.textContent = `Generating ZIP: ${Math.round(metadata.percent)}%`
},
)
const url = URL.createObjectURL(content)
const a = document.createElement('a')
a.href = url
a.download = 'archive.zip'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
setTimeout(() => URL.revokeObjectURL(url), 60000)
progressElement.textContent = 'ZIP download started'
} catch (error) {
console.error('Error generating ZIP:', error)
progressElement.textContent = 'Error generating ZIP file'
}
}
document.getElementById('zipButton').addEventListener('click', () => {
if (selectedFiles.length > 0) {
createZip(selectedFiles)
} else {
alert('Please select or drop files first.')
}
})
Umgang mit großen Dateien und Performance-Aspekte
Die clientseitige ZIP-Erzeugung ist praktisch, hat aber Grenzen:
- Speicherverbrauch: Große Dateien können viel Arbeitsspeicher belegen.
- Performance: Die Verarbeitung großer Dateien kann den Browser verlangsamen.
- Browser-Beschränkungen: Verschiedene Browser haben unterschiedliche Speichergrenzen.
So mildern Sie diese Probleme ab:
- Setzen Sie Größenbeschränkungen für Dateien um (wie im Beispiel gezeigt).
- Geben Sie Nutzern während der Verarbeitung mithilfe von Fortschrittsanzeigen Rückmeldung.
- Erwägen Sie, die Komprimierung in einen Web Worker zu verlagern, damit die Oberfläche
reaktionsfähig bleibt. Ein Worker benötigt weiterhin genügend Arbeitsspeicher für seine Eingaben
und die Ausgabe;
generateAsync({type: 'blob'})streamt das entstehende Archiv nicht auf die Festplatte.
Browser-Kompatibilität
Verwenden Sie einen modernen Browser mit FileReader, Blob-URLs, Promises sowie async/await. Behalten Sie einen Fallback über ein
Datei-Eingabefeld für Geräte bei, auf denen das Ziehen von Dateien nicht verfügbar ist, und testen
Sie die tatsächlichen Zielbrowser, statt anzunehmen, dass Unterstützung für die File API auch
Unterstützung für jedes hier verwendete JavaScript-Feature bedeutet.
Bewährte Verfahren und häufige Fallstricke
- Fehlerbehandlung: Fangen Sie Fehler in jedem Schritt kontrolliert ab.
- Größenbeschränkungen für Dateien: Informieren Sie Nutzer klar über Beschränkungen der Dateigröße.
- Fortschrittsanzeigen: Geben Sie während der Verarbeitung visuelles Feedback.
- Speicherverwaltung: Geben Sie Objekt-URLs nach der Verwendung mit
URL.revokeObjectURL()wieder frei. - Komprimierungsstufen: Finden Sie die Balance zwischen Dateigröße und Performance (höhere Komprimierung = langsamere Verarbeitung).
- Dateibenennung: Behandeln Sie doppelte Dateinamen, um Überschreibungen im ZIP zu verhindern.
- Tests: Testen Sie in verschiedenen Browsern sowie mit unterschiedlichen Dateitypen und -größen.
Fazit
ZIP-Archive direkt im Browser mit JSZip und der HTML5 File API zu erzeugen ist unkompliziert und bringt Vorteile für Nutzer wie für Server. Für Produktivumgebungen sollten Sie Größenbeschränkungen für Dateien und Fortschrittsanzeigen umsetzen, um eine reibungslose Nutzererfahrung sicherzustellen.
