gildas-lormeau/zip.js

ZIPs created via zip.js cannot be unzipped on older macOS versions with the default Archive Utility

szbotms opened this issue · 2 comments

Hi,

When a zip is created via zip.js and later tried to be opened on a user's machine which runs an older version of macOS, the default Archive Utility cannot unzip it as it results in an error. Any zip file created with the ZipManager demo is affected in the same way too.
The error is "Error 2 - No such file or directory" (in case of High Sierra and Mojave).

When unzipping it via the unzip command, it works without an issue and I assume it would work with 3rd party unarchiver apps too, but our use-case cannot require that the user has such tool installed.

When zip -F is ran on the zip file, it does not output any specific issues with the original archive, but the resulting archive can be unzipped via the Archive Utility:

zip -F test.zip --out test_fixed.zip
Fix archive (-F) - assume mostly intact archive
Zip entry offsets do not need adjusting
 copying: testdir/
 copying: testdir/content.txt

When looking at the original and the fixed zip via zipinfo -v, I only see 2 differences:

  • The file size is smaller for the fixed zip (446 vs 422) and the difference in file size is exactly the same as the difference of the central directory offset (215 vs 191).
  • For each entry, the extended local header is no in the fixed file, while it is yes in the archive which was created via zip.js

Not sure if there's any other differences between the zip files as I could only extract this much information.

Here are the files which I've tested with:
Original zip created via zip.js, using the ZipManager demo: test.zip
File created via running zip -F on the test.zip file, on the machine which could not open it: test_fixed.zip

I've tried to disable the extendedTimestamp and the dataDescriptor option in our code which calls exportUint8Array, but it resulted in the same behaviour.

Is there any way to get a resulting zip file which can be opened on these machines (so it matches the fixed zip file)?

Could you tell me if the file generated by this test works? It weights 422 bytes.

https://plnkr.co/edit/5dv0KFbxzKAHz9j3?preview

I updated the code in order to use the FS API.

Here is the code below:

<!DOCTYPE html>

<html>
  <head>
    <title>Test zip.js (FS)</title>
  </head>

  <body>
    <script type="module">
      import * as zip from "https://deno.land/x/zipjs/index.js";

      async function test() {
        // Generate ZIP file
      	const fs = new zip.fs.FS();
        const directory = fs.addDirectory("testdir");
        directory.addText("content.txt", "test content");
        const uint8Array = await fs.exportUint8Array({ 
          dataDescriptor: false 
        });
        
        // Download ZIP file
        const blob = new Blob([uint8Array], { type: "application/zip" });
        const link = document.createElement("a");
        link.href = URL.createObjectURL(blob);
        link.download = "test.zip";
        link.click();
      }

      test();
    </script>
  </body>
</html>