views:

1677

answers:

3

I want to display OpenOffice files, .odt and .odp at client side using a web browser.

These files are zipped files. Using Ajax, I can get these files from server but these are zipped files. I have to unzip them using JavaScript, I have tried using inflate.js, http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt, but without success.

How can I do this?

A: 

Unzipping a ZIP archive in JavaScript - even if it is possible using some library - is crazy. I think it's no coincidence that there's /amuse/ in the file path you link to. It's very likely, if not guaranteed, to crash browsers left and right when dealing with files larger than a few hundred kilobytes.

Proper unzipping methods are available just one click away, in the user's OS. I would leave it to them to handle the file.

Pekka
there are some cases where it could be useful to unzip in js. Some file formats are based on zip and having client side access to those would provide some advantages (e.g. cbz - http://en.wikipedia.org/wiki/Comic_Book_Archive_file)
Bala Clark
A: 

Code example is given on the author site's. You can use babelfish to translate the texts (Japanese to English).

As far as I understand Japanese, this zip inflate code is meant to decode ZIP data (streams) not ZIP archive.

OcuS
+6  A: 

I wrote an unzipper in Javascript. It works.

It relies on Andy G.P. Na's binary file reader and some RFC1951 deflate logic from notmasteryet. I added the ZipFile class.

The source and a demo page is available here:
http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip

Included there is a ZipFile.htm demonstration page, and 3 distinct scripts, one for the zipfile class, one for the inflate class, and one for a binary file reader class. The demo also depends on jQuery and jQuery UI. If you just download the js-zip.zip file, all of the necessary source is there.


Here's what the application code looks like in 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));
    }
}

The demo just blindly unzips all the content of the provided zip file. You could imagine allowing the user to select which entries to unzip, or doing something other than directly displaying the content. You could imagine, for example, zipping up a set of large XML files, and unzipping them on demand.


I agree though, with Pekka, that the idea is sort of crazy.

For one thing: It's very slow. Takes ~4 seconds to unzip the 140k AppNote.txt file from PKWare. The same uncompress can be done in less than .5s in a .NET program.

For another: it does not do streaming. It basically slurps in the entire contents of the zipfile into memory. In a "real" programming environment you could read in only the metadata of a zip file (say, 64 bytes per entry) and then read and decompress the other data as desired. There's no way to do IO like that in javascript, as far as I know, therefore the only option is to read the entire zip into memory and do random access in it. This means it will place unreasonable demands on system memory for large zip files.

Also: It doesn't handle the "general case" zip file - there are lots of zip options that I didn't bother to implement in the unzipper - like ZIP encryption, WinZip encryption, zip64, and so on. The ZipFile class handles the basics, though.

I also did not test the case for unzipping binary content. Right now it unzips text. If you have a zipped binary file, you'd need to edit the ZipFile class to handle it properly. I didn't figure out how to do that cleanly. It does binary files now, too.


EDIT - I updated the JS unzip library and demo. It now does binary files, in addition to text. I've made it more resilient and more general - you can now specify the encoding to use when reading text files. Also the demo is expanded - it shows unzipping an XLSX file in the browser, among other things.

Still the same URL: http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip

Also, I still think it is sort of a crazy idea.

Cheeso
Cheeso: :) :) Is it available to look at somewhere?
Pekka
yes, I edited the answer and added links.
Cheeso