Create a Zip with full control over content - icsharpcode/SharpZipLib GitHub Wiki
Code Reference / Zip Samples / Create a Zip with full control over content
This sample illustrates many aspects:
- multiple entries
- entry name correction
- passwords and encryption options
- Zip64 format issues.
While this example is purely disk files, the next following example shows how to use memory stream for input and output.
using System;
using System.IO;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
// Compresses the files in the nominated folder, and creates a zip file
// on disk named as outPathname.
public void CreateSample(string outPathname, string password, string folderName) {
using(FileStream fsOut = File.Create(outPathname))
using(var zipStream = new ZipOutputStream(fsOut)) {
//0-9, 9 being the highest level of compression
zipStream.SetLevel(3);
// optional. Null is the same as not setting. Required if using AES.
zipStream.Password = password;
// This setting will strip the leading part of the folder path in the entries,
// to make the entries relative to the starting folder.
// To include the full path for each entry up to the drive root, assign to 0.
int folderOffset = folderName.Length + (folderName.EndsWith("\\") ? 0 : 1);
CompressFolder(folderName, zipStream, folderOffset);
}
}
// Recursively compresses a folder structure
private void CompressFolder(string path, ZipOutputStream zipStream, int folderOffset) {
var files = Directory.GetFiles(path);
foreach (var filename in files) {
var fi = new FileInfo(filename);
// Make the name in zip based on the folder
var entryName = filename.Substring(folderOffset);
// Remove drive from name and fix slash direction
entryName = ZipEntry.CleanName(entryName);
var newEntry = new ZipEntry(entryName);
// Note the zip format stores 2 second granularity
newEntry.DateTime = fi.LastWriteTime;
// Specifying the AESKeySize triggers AES encryption.
// Allowable values are 0 (off), 128 or 256.
// A password on the ZipOutputStream is required if using AES.
// newEntry.AESKeySize = 256;
// To permit the zip to be unpacked by built-in extractor in WinXP and Server2003,
// WinZip 8, Java, and other older code, you need to do one of the following:
// Specify UseZip64.Off, or set the Size.
// If the file may be bigger than 4GB, or you do not need WinXP built-in compatibility,
// you do not need either, but the zip will be in Zip64 format which
// not all utilities can understand.
// zipStream.UseZip64 = UseZip64.Off;
newEntry.Size = fi.Length;
zipStream.PutNextEntry(newEntry);
// Zip the file in buffered chunks
// the "using" will close the stream even if an exception occurs
var buffer = new byte[4096];
using (FileStream fsInput = File.OpenRead(filename)) {
StreamUtils.Copy(fsInput, zipStream, buffer);
}
zipStream.CloseEntry();
}
// Recursively call CompressFolder on all folders in path
var folders = Directory.GetDirectories(path);
foreach (var folder in folders) {
CompressFolder(folder, zipStream, folderOffset);
}
}
Imports System
Imports System.IO
Imports ICSharpCode.SharpZipLib.Core
Imports ICSharpCode.SharpZipLib.Zip
' Compresses the files in the nominated folder, and creates a zip file on disk named as outPathname.
'
Public Sub CreateSample(outPathname As String, password As String, folderName As String)
Using fsOut As FileStream = File.Create(outPathname)
Using zipStream As New ZipOutputStream(fsOut)
'0-9, 9 being the highest level of compression
zipStream.SetLevel(3)
' optional. Null is the same as not setting.
zipStream.Password = password
' This setting will strip the leading part of the folder path in the entries,
' to make the entries relative to the starting folder.
' To include the full path for each entry up to the drive root, assign to 0.
Dim folderOffset As Integer = folderName.Length + (If(folderName.EndsWith("\"), 0, 1))
CompressFolder(folderName, zipStream, folderOffset)
End Using
End Using
End Sub
' Recurses down the folder structure
'
Private Sub CompressFolder(path As String, zipStream As ZipOutputStream, folderOffset As Integer)
Dim files As String() = Directory.GetFiles(path)
For Each filename As String In files
Dim fi As New FileInfo(filename)
' Make the name in zip based on the folder
Dim entryName As String = filename.Substring(folderOffset)
' Remove drive from name and fix slash direction
entryName = ZipEntry.CleanName(entryName)
Dim newEntry As New ZipEntry(entryName)
' Note the zip format stores 2 second granularity
newEntry.DateTime = fi.LastWriteTime
' Specifying the AESKeySize triggers AES encryption. Allowable values are 0 (off), 128 or 256.
' newEntry.AESKeySize = 256;
' To permit the zip to be unpacked by built-in extractor in WinXP and Server2003, WinZip 8, Java, and other older code,
' you need to do one of the following: Specify UseZip64.Off, or set the Size.
' If the file may be bigger than 4GB, or you do not need WinXP built-in compatibility, you do not need either,
' but the zip will be in Zip64 format which not all utilities can understand.
' zipStream.UseZip64 = UseZip64.Off;
newEntry.Size = fi.Length
zipStream.PutNextEntry(newEntry)
' Zip the file in buffered chunks
' the "using" will close the stream even if an exception occurs
Dim buffer As Byte() = New Byte(4095) {}
Using streamReader As FileStream = File.OpenRead(filename)
StreamUtils.Copy(streamReader, zipStream, buffer)
End Using
zipStream.CloseEntry()
Next
Dim folders As String() = Directory.GetDirectories(path)
For Each folder As String In folders
CompressFolder(folder, zipStream, folderOffset)
Next
End Sub