我要显示 OpenOffice文件,.odt 和 .odp 在客户端使用 Web 浏览器。
这些文件是压缩文件。使用 Ajax,我可以从服务器获取这些文件,但这些文件是压缩文件。我必须使用 JavaScript 解压它们, 我试过使用 inflate.js, http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt ,但没有成功。
我该怎么做?
最佳答案
我用Javascript编写了一个解压缩器。它有效。
它依赖于 Andy G.P. Na's binary file reader和 some RFC1951 inflate logic from notmasteryet .我添加了 ZipFile 类。
工作示例:
http://cheeso.members.winisp.net/Unzip-Example.htm (死链接)
来源:
http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip (死链接)
备注 :链接已死;我很快就会找到一个新的主人。
源代码中包含一个 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 文件。当读取完成时有一个异步回调(对于合理大小的 zip,通常在不到一秒的时间内发生) - 在这个演示中,回调保存在 doneReading 局部变量中,它只是调用 extractEntries
, 其中只是盲目地解压缩提供的 zip 文件的所有内容。在真实的应用程序中,您可能会选择一些要提取的条目(允许用户选择,或以编程方式选择一个或多个条目等)。
extractEntries
fn 遍历所有条目,并调用 extract()
在每一个上,传递一个回调。一个条目的解压需要时间,对于 zipfile 中的每个条目可能需要 1 秒或更长时间,这意味着异步是合适的。提取回调只是将提取的内容添加到页面上的 jQuery Accordion 中。如果内容是二进制的,那么它会被格式化(未显示)。它有效,但我认为该实用程序有些有限。
一方面:它非常慢。从 PKWare 解压 140k AppNote.txt 文件需要大约 4 秒。在 .NET 程序中,同样的解压缩可以在不到 0.5 秒的时间内完成。 编辑 :在 IE9 和 Chrome 中,Javascript ZipFile 的解包速度比现在快得多。它仍然比编译的程序慢,但对于正常的浏览器使用来说已经足够快了。
另一个:它不做流媒体。它基本上将 zipfile 的全部内容放入内存中。在“真实”的编程环境中,您只能读取 zip 文件的元数据(例如,每个条目 64 字节),然后根据需要读取和解压缩其他数据。据我所知,在 javascript 中没有办法像那样做 IO,因此唯一的选择是将整个 zip 读入内存并在其中进行随机访问。这意味着它会对大型 zip 文件的系统内存提出不合理的要求。对于较小的 zip 文件来说问题不大。
另外:它不处理“一般情况”的 zip 文件——有很多 zip 选项我没有费心在解压器中实现——比如 ZIP 加密、WinZip 加密、zip64、UTF-8 编码的文件名等等上。 ( 编辑 - 它现在处理 UTF-8 编码的文件名)。不过, ZipFile 类处理基础知识。其中一些事情并不难实现。我有 an AES encryption class在 JavaScript 中;可以集成以支持加密。对于大多数 Javascript 用户来说,支持 Zip64 可能没用,因为它旨在支持 >4gb 的 zipfiles - 不需要在浏览器中提取它们。
我也没有测试解压缩二进制内容的情况。现在它解压缩文本。如果你有一个压缩的二进制文件,你需要编辑 ZipFile 类来正确处理它。我不知道如何干净地做到这一点。它现在也处理二进制文件。
编辑 - 我更新了 JS 解压库和演示。除了文本之外,它现在还处理二进制文件。我使它更具弹性和更通用 - 您现在可以指定在读取文本文件时使用的编码。演示也得到了扩展 - 它显示了在浏览器中解压缩 XLSX 文件等。
所以,虽然我认为它的实用性和兴趣有限,但它确实有效。我想它可以在 Node.js 中工作。
关于javascript - 解压文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2095697/