Xceed .NET Libraries Documentation
Welcome to Xceed Data Manipulation Compoents for .NET and .NET Standard / Task-Based Help / Zip and streaming capabilities / Unzipping / Reading and writing nested Zip archives
In This Topic
    Reading and writing nested Zip archives
    In This Topic

    The following examples show how to use the ZipReader.GetItemDataStream and ZipWriter.GetItemDataStream methods to allow the component to easily handle nested zip archives.

    A nested zip archive is when an item in an archive is another zip archive. By providing the stream returned by the method to a new instance of ZipWriter or ZipReader, a nested zip file will be created or read.

    The first example shows how the ZipWriter.GetItemDataStream() method can be used to create a nested Zip archive.

    private void NestedArchiveExample( Stream someStream )
    {
      using( ZipWriter writer = new ZipWriter( someStream ) )
      {
        ZipItemLocalHeader header = new ZipItemLocalHeader();
    
        header.FileName = "File1.zip";
        writer.WriteItemLocalHeader( header );
    
        // Create a write stream that wraps the item's data
        using( Stream itemStream = writer.GetItemDataStream() )
        {
          // Feed the item stream to a new instance of ZipWriter
          using( ZipWriter nestedWriter = new ZipWriter( itemStream ) )
          {
            /* The 'using' statement will insure the nested zip file is properly terminated */
    
            // Add an item and some data into the nested zip file
            header.FileName = "File1.dat";
            nestedWriter.WriteItemLocalHeader( header );
            nestedWriter.WriteItemData( MediumFile1 );
          }
        }
      }
    }
    Private Sub NestedArchiveExample(ByVal someStream As Stream)
      Using writer As New ZipWriter(someStream)
        Dim header As New ZipItemLocalHeader()
    
        header.FileName = "File1.zip"
        writer.WriteItemLocalHeader(header)
    
        ' Create a write stream that wraps the item's data
        Using itemStream As Stream = writer.GetItemDataStream()
          ' Feed the item stream to a new instance of ZipWriter
          Using nestedWriter As New ZipWriter(itemStream)
            ' The 'using' statement will insure the nested zip file is properly terminated
    
            ' Add an item and some data into the nested zip file
            header.FileName = "File1.dat"
            nestedWriter.WriteItemLocalHeader(header)
            nestedWriter.WriteItemData(MediumFile1)
          End Using
        End Using
      End Using
    End Sub

    The second example shows how the ZipReader.GetItemDataStream method can be used to read a nested Zip archive.

    private void ReadZipArchive( Stream archiveStream )
    {
      using( ZipReader reader = new ZipReader( archiveStream ) )
      {
        ZipItemLocalHeader header;
    
        while( ( header = reader.ReadItemLocalHeader() ) != null )
        {
          /* The component will not automatically identity what is and is
          * not a nested zip file. The application needs to have its own mechanism.
          *
          * This example will keep it simple and just look at the item's file name extension. */
    
          // If the item's extension is .zip
          if( StringComparer.OrdinalIgnoreCase.Compare( Path.GetExtension( header.FileName ), ".zip" ) == 0 )
          {
            // Create a read stream that wraps the item's data
            using( Stream itemStream = reader.GetItemDataStream() )
            {
              /* NOTE: While using a recursive call here makes for elegant and compact code that
              * helps illustrate the concept of nested zip archives, a maliciously crafted zip file
              * made up of a large number of nested zip files could make this code cause a stack overflow
              * due to excessive recursion. */
    
              // Call ourselves to read the nested archive
              this.ReadZipArchive( itemStream );
            }
    
            /* IMPORTANT: Before we can move on to the next item in the archive, ZipReader must have
            * reached the end of the current item's data. Reading a nested zip file does not ensure
            * this, so we need to make sure here by reading any remaining data into a dummy stream.
            *
            * Failure to do this will result in a ZipReaderException that reports that the object
            * is not in the correct state to read the next item header. */
    
            // Make sure we reach the end of the item's data
            reader.ReadItemData( Stream.Null );
          }
          else
          {
            // This example does not concern itself with normal items
            reader.ReadItemData( Stream.Null );
          }
        }
      }
    }
    Private Sub ReadZipArchive(ByVal archiveStream As Stream)
      Using reader As New ZipReader(archiveStream)
        Dim header As ZipItemLocalHeader
    
        header = reader.ReadItemLocalHeader()
        Do While header IsNot Nothing
    '      The component will not automatically identity what is and is
    '      not a nested zip file. The application needs to have its own mechanism.
    '     
    '      This example will keep it simple and just look at the item's file name extension.
    
          ' If the item's extension is .zip
          If StringComparer.OrdinalIgnoreCase.Compare(Path.GetExtension(header.FileName), ".zip") = 0 Then
            ' Create a read stream that wraps the item's data
            Using itemStream As Stream = reader.GetItemDataStream()
    '          NOTE: While using a recursive call here makes for elegant and compact code that
    '          helps illustrate the concept of nested zip archives, a maliciously crafted zip file
    '          made up of a large number of nested zip files could make this code cause a stack overflow
    '          due to excessive recursion.
    
              ' Call ourselves to read the nested archive
              Me.ReadZipArchive(itemStream)
            End Using
    
    '        IMPORTANT: Before we can move on to the next item in the archive, ZipReader must have
    '        reached the end of the current item's data. Reading a nested zip file does not ensure
    '        this, so we need to make sure here by reading any remaining data into a dummy stream.
    '       
    '        Failure to do this will result in a ZipReaderException that reports that the object
    '        is not in the correct state to read the next item header.
    
            ' Make sure we reach the end of the item's data
            reader.ReadItemData(Stream.Null)
          Else
            ' This example does not concern itself with normal items
            reader.ReadItemData(Stream.Null)
          End If
          header = reader.ReadItemLocalHeader()
        Loop
      End Using
    End Sub