Create, read and edit .zip files with Javascript

Overview

JSZip Build Status Code Climate

Selenium Test Status

A library for creating, reading and editing .zip files with JavaScript, with a lovely and simple API.

See https://stuk.github.io/jszip for all the documentation.

var zip = new JSZip();

zip.file("Hello.txt", "Hello World\n");

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

zip.generateAsync({type:"blob"}).then(function(content) {
    // see FileSaver.js
    saveAs(content, "example.zip");
});

/*
Results in a zip containing
Hello.txt
images/
    smile.gif
*/

License

JSZip is dual-licensed. You may use it under the MIT license or the GPLv3 license. See LICENSE.markdown.

Comments
  • Can't generate zip file of images

    Can't generate zip file of images

    I'm developing a script that fetches a series of images ( that can be either png or jpg ), encodes them in base64 and zip them. Everything seems to work as expected except for the generate function that throws an error: TypeError: transform[inputType] is undefined After some digging I saw that at some point the function exports.transformTo receives as input and empty Uint8Array that when passed to exports.getTypeOf from var inputType = exports.getTypeOf(input); doesn't return anything ( for reasons I can't get ). This is the code in JSZip that creates issues:

    exports.transformTo = function(outputType, input) {
        if (!input) {
            // undefined, null, etc
            // an empty string won't harm.
            input = "";
        }
        if (!outputType) {
            return input;
        }
        exports.checkSupport(outputType);
        var inputType = exports.getTypeOf(input);
        var result = transform[inputType][outputType](input);
        return result;
    };
    
    /**
     * Return the type of the input.
     * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer.
     * @param {Object} input the input to identify.
     * @return {String} the (lowercase) type of the input.
     */
    exports.getTypeOf = function(input) {
        if (typeof input === "string") {
            return "string";
        }
        if (Object.prototype.toString.call(input) === "[object Array]") {
            return "array";
        }
        if (support.nodebuffer && nodeBuffer.test(input)) {
            return "nodebuffer";
        }
        if (support.uint8array && input instanceof Uint8Array) {
            return "uint8array";
        }
        if (support.arraybuffer && input instanceof ArrayBuffer) {
            return "arraybuffer";
        }
    };
    

    While this one is part of the code I wrote:

    var chapterImgs = new Array();
    function convertImgToBase64(image, callback, outputFormat){
        var canvas = document.createElement('CANVAS');
        var ctx = canvas.getContext('2d');
        var img = new Image;
        img.src = image[0];
        img.width = image[1];
        img.height = image[2];
        canvas.height = img.height;
        canvas.width = img.width;
        ctx.drawImage(img,0,0);
        var dataURL = canvas.toDataURL(outputFormat || 'image/png');
        callback.call(this, dataURL);
        canvas = null;
    }
    function getChapterImgs(result){
        $.each(result,function(i,property){
            chapterImgs.push(new Array("http://cdn.mangaeden.com/mangasimg/"+property[1],property[2],property[3]));
        });
        chapterImgs.reverse();
    }
    $(document).ready(function(){
    
        //Here some other code goes on...
    
        $.getJSON("//www.mangaeden.com/api/chapter/"+manga[4]+'/').done(function(pages){
            getChapterImgs(pages.images);
            $.each(chapterImgs,function(i,image){
                var format = image[0].split('.');
                if(format[3] === 'jpg')
                    convertImgToBase64(image,function(data){
                        var imgBase64 = data.split('base64,');
                        zip.file(i+'.jpg',imgBase64[1],{base64: true});
                },'image/jpeg');
                else
                    convertImgToBase64(image,function(data){
                        var imgBase64 = data.split('base64,');
                        zip.file(i+'.png',imgBase64[1],{base64: true});
                    });
            });
            if(JSZip.support.blob){
                try {
                    // console.dir(zip);
                    var blob = zip.generate({type: "blob"});
                    saveAs(blob,"chapter.zip");
                } catch(e){
                    console.log("Exception!!");
                    console.log(e);
                }
            }
        });     
    });
    

    Would love some help!

    bug 
    opened by Kwbmm 18
  • compress .gif file error

    compress .gif file error

    I want to compress a .gif file by using jszip in node js, the code is like this:

    var fileContent = fs.readFileSync("loading.gif", 'base64');
    zip.file('loading.gif', fileContent, {base64: true});
    var data = zip.generate({type: 'nodebuffer', compression: 'DEFLATE'});
    fs.writeFileSync( '/loading.zip', data, 'binary');
    

    The code can run and the zip file can be generated. However, the .gif file can't be decompressed correctly. loading

    opened by qlqllu 18
  • Solution to writing large zip's in browsers

    Solution to writing large zip's in browsers

    StreamSaver.js uses the w3c Stream API and isn't so different from the node version. streams is all good and that but it also solves another problem, which is memory, this will also write to the hard drive from the browser all asynchronous

    Thought you would be interested in StreamSaver.js. I have been able to write 16+ GB of data to the disk without any problem

    One gotcha is: it only works in Chrome and Opera

    can solve issues like #5 #227 #343

    opened by jimmywarting 16
  • browserify build

    browserify build

    first stab at it pretty much an updated version of the one currently up there, need to get the tests passing in node (browser works) which may be a challenge for me as I don't really know quint well (as opposed to mocha).

    opened by calvinmetcalf 16
  • [suggestion] Reduce crc32 code size

    [suggestion] Reduce crc32 code size

    Current crc32 implementation contains constants table, that can be generated on the fly without noticeable delay. See implementation, used in pako https://github.com/nodeca/pako/blob/master/lib/zlib/crc32.js

    Also, i'm not sure, that it's good idea (perfomance) to define table every time when function called. Probably it worth move table outside of crc32 scope (i didn't tested performance).

    performance 
    opened by puzrin 15
  • Add comment support

    Add comment support

    This commit adds the ability to read and generate comments on the zip file and/or on each zip entry, see #134. The entry comment is set on ZipObject#comment and the zip file main comment is set on JSZip#comment. For example :

    var zip = new JSZip(data);
    zip.comment // contains the comment of the loaded zip
    zip.generate({type:"blob", comment: "other comment"}); // generate a zip with a new comment
    
    zip.file("Hello.txt").comment // contains the comment of the loaded entry, if any
    zip.file("World.txt", "content", {comment : "comment here"}); // create a new file with a comment
    

    I also had issues with saucelabs tests and I resolved them with an upgrade of the grunt plugin (I also upgraded other dev dependencies).

    opened by dduponchel 15
  • Is there a way to load files into the Zip from remote URL?

    Is there a way to load files into the Zip from remote URL?

    Is there some way to load the files into the Zip from given URLs?? For example something like this:

    var zip = new JSZip();
    zip.file("Hello.txt", "http://mywebsite.com/files/Hello.txt");
    
    feature 
    opened by diegocvl 15
  • Extension missing in Chrome 15 on Windows

    Extension missing in Chrome 15 on Windows

    For example on http://jszip.stuartk.co.uk/ when click "Run" it prompts you to save the file "download" and it does not have ".zip" extension. If I save it and rename the file to "download.zip" everything is fine, but I think that the file should be by default saved with a ".zip" extension.

    opened by bogtan 15
  • Improve browser testing

    Improve browser testing

    I've updated the selection of browser on which the libraries is tested.

    index.html should be probably updated.

    It is important nowadays to asses that the library is functiioning on IE11, Edge, and latest Android / Iphone that are all missing.

    I would be a nice to have to start assessing also the code coverage of the tests exectuted on the library, and this would allow to spot deadbranches and outdated code.

    opened by evilaliv3 14
  • `D` attribute missing from folder when a file in a subfolder is added

    `D` attribute missing from folder when a file in a subfolder is added

    In a case like this:

    var zip = new JSZip();
    zip.file('subdir/test.txt', 'a test file');
    /// ... etc
    

    When the created zip is opened in 7zip or another zip program that shows the attributes of each entry in the zip file, the subdir folder exists, but the D (directory) attribute is not present. This causes problems for decompression libraries that use that attribute to check for the presence of directories within the zip. The .folder method seems to create the attribute, however.

    In addition, the Method listed for folders should generally be store (vs deflate for files), but is empty when executing the above example.

    bug 
    opened by isochronous 14
  • How to zip a pdf or ppt file using jszip?

    How to zip a pdf or ppt file using jszip?

    I want zip a pdf or some other format like excel, ppt etc using jszip.

    How to zip this format in jszip?

    My code is as below

    <BODY>
      <a id ='file' href="data/some.pdf" type="application/pdf; length=432628">Some.pdf</a>
      <input id="button" type="button" onclick="create_zip()" value="Create Zip"></input>
    </BODY>
    <SCRIPT>
            function create_zip() {
            var data = document.getElementById('file');
                var zip = new JSZip();
                zip.add(data, {base64: true});
                content = zip.generate();
                location.href = "data:application/zip;base64," + content;
            }
    </SCRIPT>
    

    What I want is that I will get the path of the file from the a element in the html. I want to zip the pdf using jszip

    question/support 
    opened by jetsonjohn 14
  • Corrupted zip : compression \x08 unknown

    Corrupted zip : compression \x08 unknown

    Hello, I've been messing around with libraries that render the contents of a docx file and all of them use JSZip internally.

    All of the libraries I've tried using throw the same JSZip error on several different documents.

    Corrupted zip : compression \x08 unknown (inner file : [)

    This shows up on every docx file load. I have tried using versions 3.10.1, 3.7.1 and 3.5.0

    Any idea what could be causing this error?

    opened by carlosfpo 0
  • No support for web streams, only node

    No support for web streams, only node

    Hi! I cannot find support for web streams ( Streams API) , only the nodeStream -->ZipObject#nodeStream(type[, onUpdate]). Adding this would be very helpful when unzipping and streaming files using jszip.

    Thanks, Jason

    opened by jasonGranholt 0
  • Possible to get real time progress when file is downloading?

    Possible to get real time progress when file is downloading?

    The current onUpdate callback in generateAsync only reflects the percentage of the file being added to the ZIP file. Is there a way to know the percentage of a file being downloaded within JSZip?

    opened by ddasutein 0
  • Invalid local file header offset for large files

    Invalid local file header offset for large files

    The tl;dr of this issue is: JSZip cannot write valid ZIP files that are larger than 4GB.

    If this is an anticipated limitation, then this issue can be closed immediately (but it should be pointed out more prominently on the "Limitations" page)


    The Central Directory Entries of ZIP files store a "relative offset of local file header". This is a 32 bit value by default. When the offset is larger than a value that can be represented with 32bits, then this value has to be 0xFFFFFFFF to indicate that the ZIP64 standard is used (See Wikipedia about ZIP64 as an entry point for the relevant specifications).

    The following program creates two archives (filled with dummy data). One of them is just so below 4GB. The other one is just so above 4GB:

    const  fs = require("fs");
    const  JSZip = require("jszip");
    
    function createFile(numFiles, fileSize, fileName) {
      const zip = new JSZip();
      const content = Buffer.alloc(fileSize);
      for (let i = 0; i < numFiles; i++) {
        zip.file("file" + i, content);
      }
      const generateOptions = {
        type: "nodebuffer",
        compression: "STORE",
        streamFiles: true,
      };
      zip
        .generateNodeStream(generateOptions)
        .pipe(fs.createWriteStream(fileName))
        .on("finish", function () {
          console.log(fileName + " written.");
        });
    }
    
    const defaultFileSize = 1000 * 1000 * 100;
    createFile(40, defaultFileSize, "jsZip_small.zip");
    createFile(45, defaultFileSize, "jsZip_large.zip");
    

    The jsZip_small.zip can be opened as usual, e.g. with the Windows Explorer. The jsZip_large.zip can not be opened. (It can be opened with 7zip, for example, but not with some other tools). The reason for that is most likely that the information from the central directory is invalid. The following is the information that is stored in the last central directory entry of that archive (the one for file44):

    indexFileDirectoryEntry: 
    headerSignature: 33639248
    versionMadeBy: 20
    versionNeeded: 10
    generalPurposeBitFlag: 8
    compressionMethod: 0
    lastModificationTime: 27148
    lastModificationDate: 21873
    uncompressedCrc32: 557995341
    compressedSize: 100000000
    uncompressedSize: 100000000
    fileNameLength: 6
    extraFieldLength: 0
    fileCommentLength: 0
    fileStartDiskNumber: 0
    internalFileAttributes: 0
    externalFileAttributes: 0
    relativeLocalFileHeaderOffset: 105034982
    fileName: file44
    extraField: java.nio.HeapByteBuffer[pos=0 lim=0 cap=0]
    fileComment: 
    

    The "relative local file header offset" is 105034982.

    Looking at this offset with a tool that can show the "real" offset of that entry, one can see that the actual offset is 4400002278. And noticing that 4400002278 = 105034982 + 232, this strongly suggests that the wrong value is the result of a plain 32bit overflow.

    The solution will likely have to happen somehwere near that line in ZipFileWorker.js: It should detect when the offset is larger than a 32 bit value, and use the ZIP64 version of the entry then. As very high-level pseudocode:

    if (offset > maxValueFor32bit) {
        dirRecord.offset = 0xFFFFFFFF; // According to ZIP64 specification
        dirRecord.extras.setOffset(number); // Set the "real" offset in the ZIP64 "extras", as an 8-byte value at offset 20
    }
    

    From my local tests: This is the same program implemented with 'archiver.js' (based on 'zip-stream'):

    const fs = require("fs");
    const archiver = require("archiver");
    
    function createFile(numFiles, fileSize, fileName) {
      const outputStream = fs.createWriteStream(fileName);
      const archive = archiver("zip", {
        store: true,
      });
      archive.pipe(outputStream);
      outputStream.on("close", () => {
        console.log(fileName + " written.");
      });
    
      const content = Buffer.alloc(fileSize);
      for (let i = 0; i < numFiles; i++) {
        archive.append(content, { name: "file" + i });
      }
      archive.finalize();
    }
    
    const defaultFileSize = 1000 * 1000 * 100;
    createFile(40, defaultFileSize, "archiver_small.zip");
    createFile(45, defaultFileSize, "archiver_large.zip");
    

    In this case, the "large" file is also valid, and looking more closely at that file, it shows that it uses the proper ZIP64 directory index format for the entries that are above the 4GB limit.

    opened by javagl 0
yet another zip library for node

yazl yet another zip library for node. For unzipping, see yauzl. Design principles: Don't block the JavaScript thread. Use and provide async APIs. Kee

Josh Wolfe 307 Dec 3, 2022
Automatically Create GIfs of a website's history

Wayback-timelapse Automatically create GIFS of a website's history if help - or to see a more userfriendly version of thes, send me a DM on twitter or

Caleb Peffer 14 Dec 9, 2022
high speed zlib port to javascript, works in browser & node.js

pako zlib port to javascript, very fast! Why pako is cool: Results are binary equal to well known zlib (now contains ported zlib v1.2.8). Almost as fa

Nodeca 4.5k Dec 30, 2022
tar-stream is a streaming tar parser and generator.

tar-stream tar-stream is a streaming tar parser and generator and nothing else. It is streams2 and operates purely using streams which means you can e

Mathias Buus 356 Jan 3, 2023
A JavaScript library to read, write, and merge ZIP archives in web browsers.

Armarius About Armarius is a JavaScript library to read, write, and merge ZIP archives in web browsers. This library mainly focuses on a low memory fo

Aternos 5 Nov 9, 2022
Automaticly parses known pocket ips patch resources, scans folders or zip files for matching roms and applies the patches.

Pocket Automaton Automaticly parses known pocket ips patch resources, scans folders or zip files for matching roms and applies the patches. Usage pock

null 3 Nov 27, 2022
Pack all your node_modules and other files you want inside your project to a zip file.

?? Node Modules Packer Use Cases | Usage | Examples | Headless | Benchmarks | Reference This is a library to package all your node_modules and other f

Vinicius Lourenço 14 Dec 1, 2022
An application that has a frontend (user interface) that allows you to create, read, update or delete (CRUD) products using an API in which you can also create, read, update or delete products.

CRUD app with React and Firebase 9 An application that has a frontend (user interface) that allows you to create, read, update or delete (CRUD) produc

Júlio Bem 3 Sep 28, 2021
Module that decompresses zip files

decompress-zip Extract files from a ZIP archive Usage .extract(options) Extracts the contents of the ZIP archive file. Returns an EventEmitter with tw

Bower 101 Sep 2, 2022
Codecs lets you use read, write, edit, and analyze images.

Codecs Codecs lets you use read, write, edit, and analyze images. npm install @astropub/codecs Usage import * as fs from 'node:fs/promises' import * a

Astro Community 8 Oct 10, 2022
yet another zip library for node

yazl yet another zip library for node. For unzipping, see yauzl. Design principles: Don't block the JavaScript thread. Use and provide async APIs. Kee

Josh Wolfe 307 Dec 3, 2022
Serve file server with single zip file as file system in Deno.

zipland Serve file server with one-single zip file in Deno. Support zip just zip32 with deflated or uncompressed serving plaintext deflate Examples Yo

Yongwook Choi 18 Nov 2, 2022
An online library for adding and removing a different number of books from a user collection, keeping track of the books you've read and the one's you are yet to read

Awesmoe Books A Website demo for our project of book store, The website has ability of adding and removing you books from yor library, Thats reflects

zieeco 11 Jul 8, 2022
Interactive web app where you can Store ,Add and Remove books to organize the books that you've read or the ones willing to read

bookStore Interactive web app where you can Store ,Add and Remove books to organize the books that you've read or the ones willing to read Built With

Yassine Omari 7 Jul 20, 2022
Read without losing the plot. Well Read helps you organize your notes about books you're reading, so you're never lost when starting a new volume.

Well Read Well Read is a website for tracking your reading of long book series. I made this to track how many pages I read in a session and to better

null 3 Dec 15, 2022
A user script for the web that allows you to view and edit files in the Godot Web Editor

Godot-Web-File-Manager This is a user script for the web that allows you to view and edit files in the Godot Web Editor. You can even use this to enab

Roujel Williams 4 Jan 31, 2022
A web interface to edit TP-Link Router Config export files (typically named config.bin).

TP-Link Router Config Editor A web interface to edit TP-Link Router Config export files (typically named config.bin). Visit the website. Tested on an

Jahed 10 Nov 17, 2022
Browser-based code editor created to edit local or server files online

notIDE Browser-based code editor created to edit local or server files online. Features Autosave while editing Syntax highlight using ace editor Creat

Mr Crypster 15 Nov 21, 2022
Tumaini Maganiko 7 May 9, 2023
NXPayload Converter is a program that allows you to create boot.dat files from Nintendo Switch payload files (.bin)

?? NXPayload Converter NXPayload Converter is a program that allows you to create boot.dat files from Nintendo Switch payload files (.bin) If you have

Murasaki 24 Dec 22, 2022