Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Create JSZip object from .zip file. #7

Closed
flying-sheep opened this Issue Oct 21, 2011 · 13 comments

Comments

Projects
None yet
3 participants

This stackoverflow answer links to a javascript class the does the reverse: Opening zip files and extracting files from it for further use.

It would be great to have a two-way zipfile object that can be created from a file, modified and downloaded as a file.

PS: the fix would answer my question here.

Collaborator

dduponchel commented Oct 22, 2011

I personally like the idea :)
I can work on it, if Stuk is interested by this feature.
If we add this, jszip API will need to change a bit : the "load-modify-generate" workflow requires more control on the included files (a get method ? ability to change directly a file ?).

currently we have this constructor:

JSZip(compression_method) or JSZip()

i propose the change:

JSZip(data_string_or_compression_method) or JSZip()

It sniffs what the string is (looks for magic number or if it is one of the supported compression methods or something), and if it detects zipped data, it reads the compression method from the file and creates the JSZip object. Else it creates an empty JSZip object with the specified or default compression method.


also currently we have these “public” methods:

  • .add(name, data, options)
    returns JSZip object this was called upon
  • .folder(name)
    returns child-JSZip object with the folder as root
  • .find(needle)
    returns an arrow of matching objects of the type {name: string, data: string, dir: true/false}
  • .remove(needle)
    recursively removes matching files/folders
    returns JSZip object this was called upon
  • .generate(asBytes)
    returns zip file from data.

i love this api, so i’d like to keep most of it. my proposed change is the following:

merge .find/.add and .find/.folder (eliminate find and rename add to file):

  • calling .file(path: string) returns the corresponding file,
    calling .file(path: regex) returns an array of matching files (like find does now),
    calling .file(path: string, data) or .file(path: string, data, options) adds the file to the matching folder, generating folders on the fly if needed, and returns the JSZip object it was called upon for chaining (kinda like add does now)
  • calling .folder(path: string) creates the folder and returns a JSZip object with the generated folder as root, which is linked to the JSZip object it was called upon (like folder does now)
    calling .folder(needle: regex) creates a list of JSZip objects that correspond to existing folders that match the regex, without creating new ones.

the file options would maybe contain a “force replacement” option. apart from that we don’t need much, except maybe a shortcut for .file(/[^/]+/) for finding all first-level files, e.g. .file()… but what do you think? maybe we should handle it like jquery, where each file list and folder list is an JSZip object itself.

Collaborator

dduponchel commented Oct 28, 2011

JSZip(data_string_or_compression_method) or JSZip()

I don't think trying to auto-detect the input is a good idea (same type (string) for compression method and data string).
The compression method should be only needed when generating the zip, so I think the generate() method is a better place. The compression currently occurs when adding a file but we should change that : giving access to a compressed content is not really useful.
What do you think of generate(asBytes) becoming generate(options) ? Where default options are :

{
    asBytes : false,
    compression : 'STORE'
}

The rest of your proposition sounds good to me !

you are of course right about generate being the better place. that’s the way to go.

the autodetection would work nicely, though. we’d just have to sniff the string.

Owner

Stuk commented Nov 21, 2011

These are all absolutely great ideas, and I love the direction going on here. If anyone fancies hacking along these lines I will happily welcome the changes. I'm going to see if I can get some spare time this week to start bringing things up to date.

Collaborator

dduponchel commented Nov 24, 2011

I should finish the code/doc/tests for the new API this week end :)

awesome!

@dduponchel dduponchel added a commit to dduponchel/jszip that referenced this issue Nov 26, 2011

@dduponchel dduponchel issue #7 : load a zip file f02df57

@dduponchel dduponchel added a commit to dduponchel/jszip that referenced this issue Nov 26, 2011

@dduponchel dduponchel issue #7 : modify the API 773196f
Collaborator

dduponchel commented Nov 26, 2011

You can see the updated doc at http://dduponchel.github.com/jszip/ and the code on my branch develop. I'm waiting your feedback !

@dduponchel dduponchel added a commit to dduponchel/jszip that referenced this issue Nov 28, 2011

@dduponchel dduponchel add tests for issue #7, use ajax (issue #6)
The ajax code has been tested in :
- IE 6 / 7 / 8 / 9
- the lastest firefox
- firefox 3.6
- the lastest opera
- the lastest chromium
- the lastest safari

The tests pass in all those browsers (except in IE 9 : the utf8 test was
broken, I didn't fixed it).
d71158b
Owner

Stuk commented Nov 29, 2011

Cheers! I'm in the middle of moving house/country at the moment, so it will take me a while to get a moment look at the code, sorry!

@dduponchel dduponchel added a commit to dduponchel/jszip that referenced this issue Dec 17, 2011

@dduponchel dduponchel jszip-load : zip64 support (enhance issue #7)
Zip64 are generated for big files (> 4GiB, not really useful in a
browser) and when a stream is compressed (the zip utility doesn't know
the size, and uses zip64 for the worst case scenario).

Two other changes :
- The parser now read things backward (end of central dir, central dir,
  local files). Reading the file backward seems odd, but the zip format
  was designed to be read like that (and I have less troubles doing so).
- I also enforced the Stuk's coding style (to be coherent with the other
  files).
482b3a9

hi, i have some problems with it. i tested it with jquery’s ajax function via python’s SimpleHTTPServer (to get around possible permission issues with local files). i used the following code:

$.ajax({
    url: "packs/johnsmith_v8.4.zip",
    dataType: "text",
    success: function(data){
        var testZip = new JSZip(data);
        console.log(testZip.file("terrain.png"));
    }
});

and this zip file (saved locally)

i get the error

End of stream reached (stream length = 4044001, asked index = 4324726). Corrupted zip ?

but zipinfo -v says:

Zip archive file size:                   4334859 (000000000042250Bh)
Actual end-cent-dir record offset:       4334837 (00000000004224F5h)
Expected end-cent-dir record offset:     4334837 (00000000004224F5h)

what cuts the stream? is it some kind of encoding issue?

PS: i tried with some more .zips, but to no avail.

Collaborator

dduponchel commented Jan 17, 2012

Hi,

That's a known issue : the browser tries to parse the ajax response as text and break it (issue #6).

The solution for firefox/chrome/opera is to use
mimeType:'text/plain; charset=x-user-defined'
instead of
dataType: "text"

The easiest way to test in IE might be to add a test case in test/index.html : the zip files are now (on my branch develop) loaded via ajax calls.

I should add a note in the documentation as the issue is not obvious !

sorry for not looking into other issues blush. thanks to you it works fine now:

$.ajaxSetup({
    mimeType: "text/plain; charset=x-user-defined",
    error: function(req, status, error) { console.error(error); }
});
Owner

Stuk commented Mar 14, 2012

Now implemented thanks to the above pull request.

@Stuk Stuk closed this Mar 14, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment