Search code examples
asp.netzipdotnetzip

Spanned archives with more than 65534 segments are not supported at this time


Our current implementation on our ASP.net website doesn't support Zip64 which it needs to, so we're moving from System.IO.Compression over to DotNetZip:
https://github.com/DinoChiesa/DotNetZip

This small archive:
https://github.com/DinoChiesa/DotNetZip/files/10184907/Zip.zip

Throws the error:

Spanned archives with more than 65534 segments are not supported at this time.

The code sample simply attempts to open the Zip file:

using (var data = new MemoryStream(fileBytes.ToArray()))
{
    using (var archive = Ionic.Zip.ZipFile.Read(data))
    {
        ....
    }

I'm a little unsure what the issue is here, is there an easy workaround or is there a better altnerative library?


Solution

  • You need to understand what does mean to have spanned zip file. That means that a zip is split into more files.

    The file you have linked appears not to be such file:

    Archive:  Zip.zip
    There is no zipfile comment.
    
    End-of-central-directory record:
    -------------------------------
    
      Zip archive file size:                    646370 (000000000009DCE2h)
      Actual end-cent-dir record offset:        646272 (000000000009DC80h)
      Expected end-cent-dir record offset:      646272 (000000000009DC80h)
      (based on the length of the central directory and its expected offset)
    
      This zipfile constitutes the sole disk of a single-part archive; its
      central directory contains 25 entries.
      The central directory is 3521 (0000000000000DC1h) bytes long,
      and its (expected) offset in bytes from the beginning of the zipfile
      is 642751 (000000000009CEBFh).
    ...
    

    I think the problem is how you try to read the file with fileBytes.ToArray(). The data variable should be a filename and not fileBytes.ToArray().

    If you look at the provided example, on how to read zip file, from the git you can see that on line 53 you get ZipFile zip = ZipFile.Read(args[0], options), where args[0] is a zip filename.

    Here is the complete example form the git:

    / ReadZip.cs
    //
    // ----------------------------------------------------------------------
    // Copyright (c) 2006-2009 Microsoft Corporation.  All rights reserved.
    //
    // This example is released under the Microsoft Public License .
    // See the license.txt file accompanying this release for
    // full details.
    //
    // ----------------------------------------------------------------------
    //
    // This simple example utility simply reads a zip archive and extracts
    // all elements in it, to the specified target directory.
    //
    // compile with:
    //     csc /target:exe /r:Ionic.Zip.dll /out:ReadZip.exe ReadZip.cs
    //
    // Wed, 29 Mar 2006  14:36
    //
    
    
    using System;
    using Ionic.Zip;
    
    namespace Ionic.Zip.Examples
    {
        public class ReadZip
        {
            private static void Usage()
            {
                Console.WriteLine("usage:\n  ReadZip2 <zipfile> <unpackdirectory>");
                Environment.Exit(1);
            }
    
    
            public static void Main(String[] args)
            {
    
                if (args.Length != 2) Usage();
                if (!System.IO.File.Exists(args[0]))
                {
                    Console.WriteLine("That zip file does not exist!\n");
                    Usage();
                }
    
                try
                {
                    // Specifying Console.Out here causes diagnostic msgs to be sent to the Console
                    // In a WinForms or WPF or Web app, you could specify nothing, or an alternate
                    // TextWriter to capture diagnostic messages.
    
                    var options = new ReadOptions { StatusMessageWriter = System.Console.Out };
                    using (ZipFile zip = ZipFile.Read(args[0], options))
                    {
                        // This call to ExtractAll() assumes:
                        //   - none of the entries are password-protected.
                        //   - want to extract all entries to current working directory
                        //   - none of the files in the zip already exist in the directory;
                        //     if they do, the method will throw.
                        zip.ExtractAll(args[1]);
                    }
                }
                catch (System.Exception ex1)
                {
                    System.Console.Error.WriteLine("exception: " + ex1);
                }
    
            }
        }
    }
    

    EDIT - the above posted zip file still generates the above error. I have checked the source to find out where is the culprit:

    It thinks it is a spanned archive based on this read. It tries to read a 2 bytes (that are converted to 16-bit unsigned integer ) from the block starting at 2nd position. If the converted value is ==0xFFFF then it considers the file as spanning file with more than 65534 segments. Probably there is some bug in the packing of the zip file which makes the DotNetZip fail.