8

I am using the javascript zip.js library. I've seach all around I a cannot find an example where more than one file is added to the zip.

Here is my code, but it generates a "corrupted" 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;
    }
});

Any idea to make it work? :)

4

2 回答 2

7

如果您正在寻找处理多个文件的良好代码示例,请参阅此处。然后您可以查看源代码

这是演示的关键来源(稍作修改):

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);

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


另一个想法:我假设您正在使用这里getBase64Image的函数,如果是这样并且您仍然遇到损坏问题,也许尝试将返回修改为简单并注释掉,因为可能期望前缀。return dataURL;.replace(...Data64URIReader

于 2013-07-07T10:29:49.427 回答
5

这是该演示的精简版本,仅使用 RAM 存储。它假定 zip.js 安装中的 zip.js、z-worker.js 和 deflate.js 与下面的两个文件以及FileSaver.js位于同一目录中。

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

演示.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>

演示.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;
    });
}
于 2015-04-19T23:16:38.877 回答