解压缩文件

时间:2010-01-19 17:54:40

标签: javascript zip unzip

我想使用网络浏览器在客户端显示OpenOffice个文件,.odt和.odp。

这些文件是压缩文件。使用Ajax,我可以从服务器获取这些文件,但这些是压缩文件。我必须使用JavaScript解压缩它们,我尝试过使用inflate.js,http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt,但没有成功。

我该怎么做?

8 个答案:

答案 0 :(得分:59)

我在Javascript中写了一个unzipper。有用。

它依赖于Andy G.P. Na's binary file readersome RFC1951 inflate logic from notmasteryet。我添加了ZipFile类。

工作实例:
http://cheeso.members.winisp.net/Unzip-Example.htm(死链接)

来源:
http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip(死链接)

NB :链接已经死亡;我很快就会找到一个新的主人。

源代码中包含一个ZipFile.htm演示页面和3个不同的脚本,一个用于zipfile类,一个用于inflate类,另一个用于二进制文件读取器类。该演示还依赖于jQuery和jQuery UI。如果您只是下载js-zip.zip文件,那么所有必需的源代码都在那里。


以下是Javascript中的应用程序代码:

// In my demo, this gets attached to a click event.
// it instantiates a ZipFile, and provides a callback that is
// invoked when the zip is read.  This can take a few seconds on a
// large zip file, so it's asynchronous. 
var readFile = function(){
    $("#status").html("<br/>");
    var url= $("#urlToLoad").val();
    var doneReading = function(zip){
        extractEntries(zip);
    };

    var zipFile = new ZipFile(url, doneReading);
};


// this function extracts the entries from an instantiated zip
function extractEntries(zip){
    $('#report').accordion('destroy');

    // clear
    $("#report").html('');

    var extractCb = function(id) {
        // this callback is invoked with the entry name, and entry text
        // in my demo, the text is just injected into an accordion panel.
        return (function(entryName, entryText){
            var content = entryText.replace(new RegExp( "\\n", "g" ), "<br/>");
            $("#"+id).html(content);
            $("#status").append("extract cb, entry(" + entryName + ")  id(" + id + ")<br/>");
            $('#report').accordion('destroy');
            $('#report').accordion({collapsible:true, active:false});
        });
    }

    // for each entry in the zip, extract it. 
    for (var i=0; i<zip.entries.length;  i++) {
        var entry = zip.entries[i];

        var entryInfo = "<h4><a>" + entry.name + "</a></h4>\n<div>";

        // contrive an id for the entry, make it unique
        var randomId = "id-"+ Math.floor((Math.random() * 1000000000));

        entryInfo += "<span class='inputDiv'><h4>Content:</h4><span id='" + randomId +
            "'></span></span></div>\n";

        // insert the info for one entry as the last child within the report div
        $("#report").append(entryInfo);

        // extract asynchronously
        entry.extract(extractCb(randomId));
    }
}

该演示分为几个步骤:readFile fn由单击触发,并实例化ZipFile对象,该对象读取zip文件。读取完成时有一个异步回调(对于合理大小的拉链,通常在不到一秒的时间内发生) - 在此演示中,回调保存在doneReading局部变量中,该变量只调用extractEntries, 只是盲目地解压缩所提供的zip文件的所有内容。在真实的应用程序中,您可能会选择一些要提取的条目(允许用户选择,或以编程方式选择一个或多个条目等)。

extractEntries fn遍历所有条目,并在每个条目上调用extract(),并传递回调。对于zipfile中的每个条目,条目的解压缩需要时间,可能是1或更多,这意味着异步是合适的。提取回调只是将提取的内容添加到页面上的jQuery手风琴中。如果内容是二进制的,则它被格式化(未示出)。


它有效,但我认为效用有限。

一方面:这很慢。从PKWare解压缩140k AppNote.txt文件大约需要4秒钟。在.NET程序中,可以在不到0.5秒的时间内完成相同的解压缩。 编辑:在IE9和Chrome中,Javascript ZipFile的解包速度比现在快得多。它仍然比编译的程序慢,但它对于正常的浏览器使用速度非常快。

另一个:它不做流式传输。它基本上将zipfile的全部内容融入到内存中。在“真实”编程环境中,您只能读取zip文件的元数据(例如,每个条目64个字节),然后根据需要读取和解压缩其他数据。据我所知,在javascript中没有办法像这样做IO,因此唯一的选择是将整个zip读入内存并在其中进行随机访问。这意味着它会对大型zip文件的系统内存提出不合理的要求。对于较小的zip文件而言,这不是一个问题。

另外:它没有处理“一般情况”的zip文件 - 我有很多拉链选项在unzipper中没有实现 - 比如ZIP加密,WinZip加密,zip64, UTF- 8个编码文件名,等。 (编辑 - 它现在处理UTF-8编码的文件名)。但是,ZipFile类处理基础知识。其中一些事情并不难实现。我在Javascript中有an AES encryption class;可以集成以支持加密。支持Zip64可能对大多数Javascript用户无用,因为它旨在支持&gt; 4gb压缩文件 - 不需要在浏览器中提取这些文件。

我也没有测试解压缩二进制内容的情况。现在它解压缩文本。如果你有一个压缩的二进制文件,你需要编辑ZipFile类来正确处理它。我没弄清楚如何干净利落地做到这一点。 它现在也是二进制文件。


编辑 - 我更新了JS解压缩库和演示。除了文本之外,它现在还会执行二进制文件。我已经使它更具弹性和更通用 - 您现在可以指定在读取文本文件时使用的编码。此外,该演示还展开了 - 它显示了在浏览器中解压缩XLSX文件等等。

所以,虽然我认为它的实用性和兴趣有限,但它确实有效。我想它可以在Node.js中使用。

答案 1 :(得分:23)

我正在使用zip.js,这似乎非常有用。值得一看!

例如,检查Unzip demo

答案 2 :(得分:9)

我发现jszip非常有用。到目前为止我只用于阅读,但他们也有创建/编辑功能。

代码明智它看起来像这样

var new_zip = new JSZip();
new_zip.load(file);
new_zip.files["doc.xml"].asText() // this give you the text in the file

我注意到的一件事是,文件似乎必须是二进制流格式(使用FileReader(。)的.readAsArrayBuffer读取,否则我收到错误,说我可能有一个损坏的zip文件

答案 3 :(得分:2)

代码示例为on the author site's。您可以使用babelfish翻译文本(日语到英语)。

据我所知日语,此zip扩充代码用于解码ZIP数据(流)而不是ZIP存档。

答案 4 :(得分:2)

我也为此写了一堂课。 http://blog.another-d-mention.ro/programming/read-load-files-from-zip-in-javascript/ 您可以使用类方法直接从zip加载基本资源,如javascript / css / images。 希望它有所帮助

答案 5 :(得分:2)

我写了#34;二进制工具JavaScript和#34;这是一个开源项目,包括解压缩,解压缩和解压缩的功能:https://github.com/codedread/bitjs

在我的漫画读者中使用:https://github.com/codedread/kthoom(也是开源)。

HTH!

答案 6 :(得分:2)

如果您还需要支持其他格式或只需要出色的性能,则可以使用此WebAssembly library

它是基于承诺的,它使用WebWorkers进行线程化,而API实际上是简单的ES模块

答案 7 :(得分:0)

如果有人正在从远程服务器上托管的zip文件中读取图像或其他二进制文件,则可以使用以下代码段通过jszip库下载并创建zip对象。

// this function just get the public url of zip file.
let url = await getStorageUrl(path) 
console.log('public url is', url)
//get the zip file to client
axios.get(url, { responseType: 'arraybuffer' }).then((res) => {
  console.log('zip download status ', res.status)
//load contents into jszip and create an object
  jszip.loadAsync(new Blob([res.data], { type: 'application/zip' })).then((zip) => {
    const zipObj = zip
    $.each(zip.files, function (index, zipEntry) {
    console.log('filename', zipEntry.name)
    })
  })

现在使用zipObj,您可以访问文件并为其创建src网址。

var fname = 'myImage.jpg'
zipObj.file(fname).async('blob').then((blob) => {
var blobUrl = URL.createObjectURL(blob)