如何使用zip.js将多个文件添加到zip中?

时间:2013-07-07 09:47:16

标签: zip javascript

我正在使用javascript zip.js库。我一直在搜索,我找不到一个例子,其中拉链中添加了多个文件。

这是我的代码,但它会生成“损坏的”zip。

var len = results.rows.length, i;
var k=1;
zip.createWriter(new zip.BlobWriter(), function(writer) {
    for (i = 0; i < len; i++){
        // get the image url from a sqlite request
        url = results.rows.item(i).url;


        var img = new Image();
        img.onload = function() {
            var a = document.createElement('a');
            a.href = this.src;
            var filename= a.pathname.split('/').pop(); // filename.php
            timest = new Date().getTime();
            // use a TextReader to read the String to add

                writer.add(timest+".jpg", new zip.Data64URIReader(getBase64Image(img)), function() {
                // onsuccess callback
                    k++;
                    if(k==len){
                        setTimeout(function(){
                        writer.close(function(blob) {

                            // blob contains the zip file as a Blob object
                            $('#test').attr("href", window.URL.createObjectURL(blob));
                            $('#test').attr("download", "woeii.zip");

                        });
                        },1000);
                    }
                }, function(currentIndex, totalIndex) {
                // onprogress callback
                });



        };
        img.src = url;
    }
});

有什么想法让它发挥作用? :)

2 个答案:

答案 0 :(得分:6)

如果您正在寻找处理多个文件的代码的好例子,see here。然后,您可以view the source code

这是演示的主要来源(略微修改):

var obj = this;
var model = (function() {
    var zipFileEntry, zipWriter, writer, creationMethod, URL = obj.webkitURL || obj.mozURL || obj.URL;

    return {
        setCreationMethod : function(method) {
            creationMethod = method;
        },
        addFiles : function addFiles(files, oninit, onadd, onprogress, onend) {
            var addIndex = 0;

            function nextFile() {
                var file = files[addIndex];
                onadd(file);
                // Modified here to use the Data64URIReader instead of BlobReader
                zipWriter.add(file.name, new zip.Data64URIReader(file.data), function() {
                    addIndex++;
                    if (addIndex < files.length)
                        nextFile();
                    else
                        onend();
                }, onprogress);
            }

            function createZipWriter() {
                zip.createWriter(writer, function(writer) {
                    zipWriter = writer;
                    oninit();
                    nextFile();
                }, onerror);
            }

            if (zipWriter)
                nextFile();
            else if (creationMethod == "Blob") {
                writer = new zip.BlobWriter();
                createZipWriter();
            } else {
                createTempFile(function(fileEntry) {
                    zipFileEntry = fileEntry;
                    writer = new zip.FileWriter(zipFileEntry);
                    createZipWriter();
                });
            }
        },
        getBlobURL : function(callback) {
            zipWriter.close(function(blob) {
                var blobURL = creationMethod == "Blob" ? URL.createObjectURL(blob) : zipFileEntry.toURL();
                callback(blobURL);
                zipWriter = null;
            });
        },
        getBlob : function(callback) {
            zipWriter.close(callback);
        }
    };
})();

使用方法: 假设存在<a id="downloadLink">Download</a>元素,以便在准备好后提供下载。

// Prepare your images
var files = [];
for (i = 0; i < len; i++) {

    // Get the image URL from a SQLite request
    var url = results.rows.item(i).url;

    (function(url){
        var img = new Image();
        img.onload = function() {
            // Add to file array [{name, data}]
            var a = document.createElement('a');
            a.href = this.src;
            var filename= a.pathname.split('/').pop();

            console.log("Loaded file " + filename);
            files.push({name: filename, data: getBase64Image(img) });
        }
        img.src = url;
    })(url);
}

// Wait for the image to load
var check = setInterval(function(){
    if(files.length==images.length) {
        clearInterval(check);

        // Set the mode
        model.setCreationMethod("Blob");

        // Add the files to the zip
        model.addFiles(files, 
            function() {
                // Initialise Method
                console.log("Initialise");
            }, function(file) {
                // OnAdd
                console.log("Added file");
            }, function(current, total) {
                // OnProgress
                console.log("%s %s", current, total);
            }, function() {
                // OnEnd
                // The zip is ready prepare download link
                // <a id="downloadLink" href="blob:url">Download Zip</a>
                model.getBlobURL(function(url) {
                    document.getElementById("downloadLink").href = url;
                    document.getElementById("downloadLink").style.display = "block";
                    document.getElementById("downloadLink").download = "filename.zip";
                });
            });

    }
}, 500);

您可以使用示例源代码添加进度指示器。 希望这会有所帮助,这个方法的优点是如果你把它变成自己的JS文件,那么zip模型很容易重复使用。


另一个想法:我假设你使用getBase64Image函数from here,如果是这样,你仍然遇到腐败问题,也许尝试将返回修改为return dataURL;并注释掉{ {1}},因为.replace(...可能需要前缀。

答案 1 :(得分:2)

这是that demo的精简版,只使用RAM存储空间。它假设zip.js安装的zip.js,z-worker.js和deflate.js与下面的两个文件位于同一目录中,同时还有FileSaver.js

注意:这不是生产就绪代码!这是我做的一个简单的演示,所以我可以弄清楚发生了什么。如果以编程方式生成并保存zip,则可能需要实现类似上面的nextFile()迭代器,以防止竞争条件使用空文件填充zip。 (有关此示例,请参阅https://stackoverflow.com/a/29738675/738675。)

<强> demo.html:

<li>
    add files into the zip
    <input type="file" multiple id="file-input" onchange="addFiles(this.files)">
</li>
<li>
    download the zip file
    <a href="#" onclick="saveZip()">Download</a>
</li>

<script type="text/javascript" src="zip.js"></script>
<script type="text/javascript" src="demo.js"></script>
<script type="text/javascript" src="FileSaver.js"></script>

<强> demo.js:

var zipWriter;

function addFiles(files) {
    writer = new zip.BlobWriter();
    zip.createWriter(writer, function(writer) {
        zipWriter = writer;
        for (var f = 0; f < files.length; f++) {
            zipWriter.add(files[f].name,
            new zip.BlobReader(files[f]), function() {});
        }
    });
}

function saveZip() {
    zipWriter.close(function(blob) {
        saveAs(blob, "Example.zip"); // uses FileSaver.js
        document.getElementById("file-input").value = null; // reset input file list
        zipWriter = null;
    });
}