Jalara Studio

veröffentlicht am

JSZip: Mit JavaScript eine .zip-Datei erstellen

#


JSZip ist eine JavaScript-Bibliothek von Stuart Knightley1, die es auf Grund der minimalen API (von engl. application programming interface; dt. Anwendungsprogrammierschnittstelle)2 sehr einfach ermöglicht, eine .zip-Datei zu erstellen, diese auszulesen oder zu editieren. JSZip ist lizenziert unter der MIT-Lizenz, sowie unter der GPL Version33. Im Folgenden soll anhand von drei Beispielen gezeigt werden, wie eine .zip-Datei mit JSZip erstellt werden kann:

JSZIP einbinden

Eingebunden werden kann die Bibliothek mit HTML wie folgt:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.4/jszip.min.js"></script>   

JSZip-Instanz erstellen

Anschießend lässt sich eine neue JSZip-Instanz erstellen:

var zip = new JSZip();

Datei erstellen

Die JSZip-Instanz zip kann nun auf die Funktion file()4 zugreifen, um beispielsweise eine Datei mit dem Namen hallo-welt.text und der darin enthaltenen Zeichenkette Hallo Welt zu erstellen:

zip.file( "hallo-welt.text", "Hallo Welt" );

Zum Erstellen der Datei kann die Funktion generateAsync()5 werden, sofern der Browser Data URI beherrscht6:

zip.generateAsync( { type:"base64" } ).then( function( base64 ) {
    location.href = "data:application/zip; base64," + base64;
} );

Beispiel 1: index.html

Folgender Quelltext einer index.html-Datei würde die beschriebene .zip-Datei bereits erstellen:

<html>
    <head><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.4/jszip.min.js"></script></head>
    <body>
        <script>
            var zip = new JSZip();
            var textData = "Hallo Welt";
            zip.file( "hallo-welt.txt", textData );
            zip.generateAsync( { type:"base64" } ).then( function( base64 ) {
                location.href="data:application/zip;base64," + base64;
            } );   
        </script>
    </body>
</hmtl>

FileSaver.js

Das Problem an der Data-URI-Methode ist jedoch nicht nur, dass der Internet Explorer diese nicht unterstützt, sondern auch der mangelnde Einfluss auf die Dateibezeichnung. Bei Firefox, Safari und Chrome (Windows) fehlt, nach der Erstellung der .zip-Datei, zudem die Dateiendung .zip.

Aus diesen Gründen kann zusätzlich die JavaScript-Datei FileSaver.js7 von Eli Grey eingebunden werden:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>   

Das Schreiben der .zip-Datei gelingt anschließend mit der Funktion saveAs():

zip.generateAsync( {type:"blob"} )
.then( function(blob) {
    saveAs( blob, "archiv.zip" );
});

Unterstützte JSZIP-Features ermitteln

Ob der Browser Blob, Uint8Array oder ArrayBuffer unterstützt, kann mit JSZip.support8 ermittelt werden:

if ( JSZip.support.arraybuffer ) {
    console.log( "ArrayBuffer wird unterstützt." );
 }
if ( JSZip.support.uint8array ) {
    console.log( "Uint8Array wird unterstützt." );
 }
 if ( JSZip.support.blob ) {
    console.log( "Blob wird unterstützt." );
 }

Wird Blob9 nicht vom Browser unterstützt, wird in der Console die entsprechende Ausgabe fehlen. In diesem Fall lässt sich als Polyfiller die JavaScript-Datei Blob.js10 – ebenfalls von Eli Grey – nutzen.

Beispiel 2: index.html (mit FileSaver.js und Blob.js)

Der Quelltext der folgenden index.html-Datei enthält neben der FileSaver-Methode und dem Blob-Polyfill auch eine Schaltfläche, die die .zip-Datei nach einem Klick erstellen wird:

<html>
    <head>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.4/jszip.min.js"></script>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/blob-polyfill/1.0.20150320/Blob.min.js"></script>   
    </head>
    <body>
    <input type="button" onclick="downloadZip()" value="Erstelle archiv.zip"></input>
    <script>
        function downloadZip() {
            var zip = new JSZip();
            var textData = "Hallo Welt";
            zip.file( "hallo-welt.txt", textData );
            zip.generateAsync( { type:"blob" } ).then( function( blob ) {
                    saveAs( blob, "archiv.zip" );
                 } );
        }
    </script>
</body>

Ordner und Bilder erstellen

Ordner und Bilder lassen sich ebenfalls mit den entsprechenden Funktionen (folder()11, file()) in der .zip-Datei erstellen. Im folgendem Beispiel wird ein zuvor mit Base64 kodiertes Bild in den Ordner bilder eingefügt:

var img = zip.folder( "bilder" );
 var imgData = "R0lGODdhBQAFAIACAAAAAP/eACwAAAAABQAFAAACCIwPkWerClIBADs=";
 img.file( "smile.gif", imgData, { base64: true } );

Tipp: Um ein Bild in einen Base64-String zu kodieren kannst du u.a. einen Generator oder die PHP-Funktion base64_encode()12 nutzen (Anwendungsbeispiel: <?php $imgData = base64_encode( file_get_contents( 'bilder/smile.gif' ) ); ?>). Einen Image-to-Base64-Generator findest du auf den Websiten hreftools13 und base64-image14.

JSZipUtils

Wer AJAX verwenden möchte, um Dateien via HTTP GET von einem Server zu holen, kann zudem die JSZip-Erweiterung JSZipUtils entsprechend einbinden:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.0.2/jszip-utils.min.js"></script>
<!--[if IE]><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.0.2/jszip-utils-ie.min.js"></script><![endif]-->

Anschließend kann mit dem Aufruf JSZipUtils und der Funktion getBinaryContent()15 das Bild der .zip-Datei hinzugefügt werden:

JSZipUtils.getBinaryContent( "pfad/bild.png", function( err, data ) {
    if ( err ) {
        throw err;
    }
    var zip = new JSZip();
    zip.file( "bild.png", data, { binary:true } );
} );

Beispiel 3: index.html (mit FileSaver.js, Blob.js und JSZipUtils)

Der Quelltext der folgenden index.html-Datei erstellt nach einem Klick auf die Schaltfläche "Erstelle archiv.zip" eine .zip-Datei mit 3 zufälligen Bildern von Unsplash und einer HTML-Datei hallo-welt.html:

Die entpackte und daraufhin im Browser geöffnete HTML-Datei hallo-welt.html wird die drei Bilder wie folgt einbinden:

<html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.4/jszip.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/blob-polyfill/1.0.20150320/Blob.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.0.2/jszip-utils.min.js"></script>
        <!--[if IE]><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.0.2/jszip-utils-ie.min.js"></script><![endif]-->
    </head>
    <body>
    <input type="button" onclick="downloadZip()" value="Erstelle archiv.zip"></input>
    <script>
        function downloadZip() {
            var bilder = [
            "https://unsplash.it/100/100?random",
            "https://unsplash.it/200/200?random",
            "https://unsplash.it/300/300?random"
            ];
            var zip = new JSZip();
            var count = 0;
            var htmlStyle ="<style>body{text-align:center;font-family:sans-serif}</style>";
            var htmlStart ="<html><head>" + htmlStyle + "</head><body><h1>Hallo Welt</h1>";
            var htmlEnde = "</body></html>";
            var htmlText = "";
            bilder.forEach(function(bild) {
                JSZipUtils.getBinaryContent(bild, function(err, data) {
                    if (err) {
                        throw err;
                    }
                    count++;
                    bild = "bild" + count + ".jpg";
                    htmlText += "<h2>" + bild + '<h2><img src="' + bild + '"><br>';
                    var htmlData = htmlStart + htmlText + htmlEnde;
                    zip.file("hallo-welt.html", htmlData);
                    zip.file(bild, data, {
                        binary: true
                    });
                    if (count == bilder.length) {
                        zip.generateAsync({ type: "blob" }).then(function(content) {
                            saveAs(content, "zipFilename.zip");
                        });
                    }
                });
            });
        }
    </script>
</body>

Links

Buchempfehlung

Anzeige | Affiliate-Link*

Wer die objektorientierte Scriptsprache JavaScript umfassend erlernen möchte, dem sei das über 1000 Seiten starke Standard­werk JavaScript - Das um­fassende Referenz­werk des Pro­gram­mierers David Flanagan empfohlen, das 2012 in der 6. Auflage im O'Reilly Verlag erschien.

Hinweis: Die 6. Auflage des Buches behandelt ECMAScript (offizielle Bezeichnung für JavaScript) in der Version 5 (kurz ES5). Der Browser Internet Explorer (kurz IE) in der Version 10 und 11 unterstützt ES5. Der IE 9 unterstützt ES5 teilweise. Neuere ES-Versionen werden erst vom Browser Edge unterstützt.