Documentation
¶
Overview ¶
Package gozip provides a high-performance, concurrency-safe, and feature-rich implementation of the ZIP archive format.
It is designed as a robust alternative to the standard library's archive/zip, specifically built for high-load applications, security-conscious environments, and developer experience.
Key Features ¶
1. Architecture: The library uses the Archiver to encapsulate configuration (passwords, codecs). No global state or side effects.
2. Usability: Includes high-level helpers (ArchiveDir, Unzip, Diff) for common tasks, reducing boilerplate code to the minimum.
3. Concurrency: Supports parallel compression and extraction, utilizing all available CPU cores for maximum throughput using WithWorkers.
4. Security: Native support for WinZip AES-256 encryption and built-in "Zip Slip" protection during extraction to prevent directory traversal attacks.
5. Abstraction: Uses Source and Sink interfaces to transparently handle files on disk, in-memory buffers, or network streams.
6. Context Awareness: All long-running operations support context.Context for cancellation and timeout management.
7. Compatibility: Handles Zip64 (files > 4GB), NTFS timestamps, Unix permissions, and legacy DOS encodings (CP437, CP866) automatically.
Quick Start ¶
The simplest way to use the library is via global helper functions that use default settings (Deflate compression):
// Archive a directory
err := gozip.ArchiveDir("data/", gozip.ToFilePath("backup.zip"))
// Extract an archive
err := gozip.Unzip(gozip.FromFilePath("backup.zip"), "restored/")
// Read a single file contents without extraction
data, err := gozip.ReadFile(gozip.FromFilePath("config.zip"), "settings.json")
Advanced Usage (The Archiver) ¶
For custom configuration (passwords, specific compression algorithms), create an Archiver instance. This allows you to isolate settings per operation.
// Configure an environment
archiver := gozip.NewArchiver(
gozip.WithArchivePassword("secure-password"),
// gozip.WithCompressor(gozip.Zstd, zstd.NewFactory()), // If using custom codecs
)
// Use the configured instance
err := archiver.Unzip(gozip.FromFilePath("encrypted.zip"), "output/")
Source & Sink ¶
The library abstracts IO operations. You can work with physical files, byte slices, or streams seamlessly:
// Unzip from memory (e.g., uploaded file)
src := gozip.FromReader(bytes.NewReader(data), int64(len(data)))
gozip.Unzip(src, "uploads/")
// Archive directly to an HTTP response
dest := gozip.ToWriter(httpResponseWriter)
gozip.ArchiveDir("report/", dest)
Error handling ¶
FileError is used for errors related to File instance and operations, allowing users to access file metadata (name, size) for logging/retry logic. Plain wrapped errors are used for global archive issues. Example:
_, err := archive.AddFile("data/report.pdf")
if err != nil {
var fileErr *gozip.FileError
if errors.As(err, &fileErr) {
fmt.Printf("Operation: %s\n", fileErr.Op) // e.g., "add", "compress", "extract"
fmt.Printf("File: %s\n", fileErr.File.Name())
fmt.Printf("Cause: %v\n", fileErr.Err) // Underlying error (e.g., [ErrPasswordMismatch])
}
}
Manual Control (Low-Level) ¶
Creating an archive:
archive := gozip.NewZip()
archive.AddFile("file.txt")
archive.AddDir("images/", WithCompression(gozip.Deflate, gozip.DeflateMaximum))
f, _ := os.Create("output.zip")
archive.WriteTo(f)
Modifying an existing archive:
archive := gozip.NewZip()
src, _ := os.Open("old.zip")
archive.LoadFromFile(src)
// 1. Remove obsolete files
archive.Remove("logs/obsolete.log")
// 2. Modify a file
files, _ := archive.Remove("data/config.json")
archive.AddLazy(files[0].Name(), func() (io.ReadCloser, error) {
pr, pw := io.Pipe()
go func() {
defer pw.Close()
rc, err := file.Open()
if err != nil {
pw.CloseWithError(err)
return
}
defer rc.Close()
processor.Transform(rc, pw)
}()
return pr, nil
})
// 3. Rename entries
archive.Rename("dir/old", "new") // -> dir/new
// Save changes to a new writer
dest, _ := os.Create("new.zip")
archive.WriteTo(dest, gozip.WithWorkers(runtime.NumCPU()))
// Close source after the work is done
src.Close()
Index ¶
- Constants
- Variables
- func ArchiveDir(srcDir string, dest Sink, opts ...ZipOption) error
- func ArchiveFiles(files []string, dest Sink, opts ...ZipOption) error
- func Clone(zip Source, dest Sink, opts ...ZipOption) error
- func DecodeCP437(s string) string
- func DecodeIBM866(s string) string
- func Exists(zip Source, filename string) (bool, error)
- func IsEncrypted(zip Source, filters ...Filter) (bool, error)
- func IsZipStream(r io.Reader) (bool, error)
- func Merge(dest Sink, sources ...Source) error
- func ReadFile(zip Source, filename string) ([]byte, error)
- func ReplaceFile(zip Source, dest Sink, filename string, content io.Reader) error
- func SafePath(destDir, fileName string) (string, error)
- func TotalSize(zip Source, filters ...Filter) (uncompressed, compressed int64, err error)
- func Transform(zip Source, dest Sink, fn TransformFunc, opts ...ZipOption) error
- func Tree(zip Source, filters ...Filter) (string, error)
- func Unzip(zip Source, destDir string, opts ...ZipOption) error
- func UnzipFile(zip Source, filename string, dest Sink) error
- func UnzipGlob(zip Source, pattern, destDir string) error
- func UnzipToMap(zip Source, filters ...Filter) (map[string][]byte, error)
- func UnzipToTemp(zip Source, prefix string, opts ...ZipOption) (path string, cleanup func(), err error)
- func UpdateMetadata(zip Source, dest Sink, modifier func(*File), opts ...ZipOption) error
- func UseSink(sink Sink, fn func(w io.Writer) error) (err error)
- func UseSource(src Source, fn func(r io.Reader, rAt io.ReaderAt, size int64) error) (err error)
- func Verify(zip Source, opts ...ZipOption) error
- func Walk(zip Source, walkFn func(*File) error, filters ...Filter) error
- type AddOption
- func WithCompression(c CompressionMethod, lvl int) AddOption
- func WithConfig(c FileConfig) AddOption
- func WithEncryption(e EncryptionMethod, pwd string) AddOption
- func WithMarkDirsImplicit() AddOption
- func WithName(name string) AddOption
- func WithPassword(pwd string) AddOption
- func WithPath(p string) AddOption
- type ArchiveDiff
- type ArchiveOption
- func WithCompressor(method CompressionMethod, factory CompressorFactory) ArchiveOption
- func WithDecompressor(method CompressionMethod, d Decompressor) ArchiveOption
- func WithImplicitDirs() ArchiveOption
- func WithStrategy(s ZipStrategy) ArchiveOption
- func WithZipCompression(c CompressionMethod, lvl int) ArchiveOption
- func WithZipConfig(cfg ZipConfig) ArchiveOption
- func WithZipEncryption(e EncryptionMethod, pwd string) ArchiveOption
- func WithZipPassword(pwd string) ArchiveOption
- type Archiver
- func (a *Archiver) ArchiveDir(srcDir string, destZip Sink, opts ...ZipOption) error
- func (a *Archiver) ArchiveDirWithContext(ctx context.Context, srcDir string, destZip Sink, opts ...ZipOption) error
- func (a *Archiver) ArchiveFiles(files []string, destZip Sink, opts ...ZipOption) error
- func (a *Archiver) ArchiveFilesWithContext(ctx context.Context, files []string, destZip Sink, opts ...ZipOption) error
- func (a *Archiver) Clone(zip Source, destZip Sink, opts ...ZipOption) error
- func (a *Archiver) CloneWithContext(ctx context.Context, zip Source, destZip Sink, opts ...ZipOption) error
- func (a *Archiver) Diff(srcA, srcB Source, filters ...Filter) (ArchiveDiff, error)
- func (a *Archiver) DiffWithContext(ctx context.Context, zipA, zipB Source, filters ...Filter) (diff ArchiveDiff, err error)
- func (a *Archiver) Exists(zip Source, filename string) (bool, error)
- func (a *Archiver) ExistsWithContext(ctx context.Context, zip Source, filename string) (bool, error)
- func (a *Archiver) GetEntries(zip Source) ([]*File, error)
- func (a *Archiver) GetEntriesWithContext(ctx context.Context, zip Source) ([]*File, error)
- func (a *Archiver) IsEncrypted(zip Source, filters ...Filter) (bool, error)
- func (a *Archiver) Merge(destZip Sink, sources ...Source) error
- func (a *Archiver) MergeWithContext(ctx context.Context, destZip Sink, sources ...Source) error
- func (a *Archiver) ReadFile(zip Source, filename string) ([]byte, error)
- func (a *Archiver) ReadFileWithContext(ctx context.Context, zip Source, filename string) ([]byte, error)
- func (a *Archiver) ReplaceFile(zip Source, dest Sink, filename string, content io.Reader) error
- func (a *Archiver) ReplaceFileWithContext(ctx context.Context, zip Source, dest Sink, filename string, content io.Reader) error
- func (a *Archiver) Search(zip Source, text string, filters ...Filter) ([]*File, error)
- func (a *Archiver) SearchWithContext(ctx context.Context, zip Source, text string, filters ...Filter) ([]*File, error)
- func (a *Archiver) TotalSize(zip Source, filters ...Filter) (uncompressed, compressed int64, err error)
- func (a *Archiver) Transform(zip Source, dest Sink, fn TransformFunc, opts ...ZipOption) error
- func (a *Archiver) TransformWithContext(ctx context.Context, zip Source, dest Sink, fn TransformFunc, ...) error
- func (a *Archiver) Tree(zip Source, filters ...Filter) (string, error)
- func (a *Archiver) TreeWithContext(ctx context.Context, zip Source, filters ...Filter) (string, error)
- func (a *Archiver) Unzip(zip Source, destDir string, opts ...ZipOption) error
- func (a *Archiver) UnzipFile(zip Source, filename string, dest Sink) error
- func (a *Archiver) UnzipFileWithContext(ctx context.Context, zip Source, filename string, dest Sink) error
- func (a *Archiver) UnzipGlob(zip Source, pattern, destDir string) error
- func (a *Archiver) UnzipGlobWithContext(ctx context.Context, zip Source, pattern, destDir string) (err error)
- func (a *Archiver) UnzipToMap(zip Source, filters ...Filter) (map[string][]byte, error)
- func (a *Archiver) UnzipToMapWithContext(ctx context.Context, zip Source, filters ...Filter) (map[string][]byte, error)
- func (a *Archiver) UnzipToTemp(zip Source, prefix string, opts ...ZipOption) (path string, cleanup func(), err error)
- func (a *Archiver) UnzipToTempWithContext(ctx context.Context, zip Source, prefix string, opts ...ZipOption) (path string, cleanup func(), err error)
- func (a *Archiver) UnzipWithContext(ctx context.Context, zip Source, destDir string, opts ...ZipOption) error
- func (a *Archiver) UpdateMetadata(zip Source, dest Sink, modifier func(*File), opts ...ZipOption) error
- func (a *Archiver) UpdateMetadataWithContext(ctx context.Context, zip Source, dest Sink, modifier func(*File), ...) error
- func (a *Archiver) Verify(zip Source, opts ...ZipOption) error
- func (a *Archiver) VerifyWithContext(ctx context.Context, zip Source, opts ...ZipOption) error
- func (a *Archiver) Walk(zip Source, walkFn func(*File) error, filters ...Filter) error
- func (a *Archiver) WalkWithContext(ctx context.Context, zip Source, walkFn func(*File) error, filters ...Filter) (err error)
- type CompressionMethod
- type Compressor
- type CompressorFactory
- type ConflictAction
- type ConflictHandler
- type Decompressor
- type DeflateCompressor
- type DeflateDecompressor
- type EncryptionMethod
- type File
- func (f *File) CRC32() uint32
- func (f *File) CompressedSize() int64
- func (f *File) Config() FileConfig
- func (f *File) FillSnapshot(snap *FileSnapshot)
- func (f *File) FsTime() (mtime, atime, ctime time.Time)
- func (f *File) GetExtraField(tag uint16) []byte
- func (f *File) HasExtraField(tag uint16) bool
- func (f *File) HostSystem() sys.HostSystem
- func (f *File) IsDir() bool
- func (f *File) IsEncrypted() bool
- func (f *File) IsImplicit() bool
- func (f *File) LocalHeaderOffset() int64
- func (f *File) ModTime() time.Time
- func (f *File) Mode() fs.FileMode
- func (f *File) Name() string
- func (f *File) Open() (io.ReadCloser, error)
- func (f *File) OpenRaw() (*io.SectionReader, error)
- func (f *File) RequiresZip64() bool
- func (f *File) SetExtraField(tag uint16, data []byte) error
- func (f *File) Snapshot() *FileSnapshot
- func (f *File) UncompressedSize() int64
- func (f *File) WithComment(c string) *File
- func (f *File) WithCompression(method CompressionMethod, level int) *File
- func (f *File) WithConfig(c FileConfig) *File
- func (f *File) WithDisableEncryption() *File
- func (f *File) WithEncryption(method EncryptionMethod, pwd string) *File
- func (f *File) WithModTime(modTime time.Time) *File
- func (f *File) WithMode(mode fs.FileMode) *File
- func (f *File) WithOpenFunc(openFunc func() (io.ReadCloser, error)) *File
- func (f *File) WithPassword(pwd string) *File
- func (f *File) WithSourcePassword(pwd string) *File
- func (f *File) WithUncompressedSize(size int64) *File
- type FileConfig
- type FileError
- type FileSnapshot
- func (s *FileSnapshot) CentralDirectory() internal.CentralDirectory
- func (s *FileSnapshot) CompressionLevelBits() uint16
- func (s *FileSnapshot) CompressionMethod() uint16
- func (s *FileSnapshot) ExternalFileAttributes() uint32
- func (s *FileSnapshot) FileBitFlag() uint16
- func (s *FileSnapshot) LocalHeader() internal.LocalFileHeader
- func (s *FileSnapshot) RequiresZip64() bool
- func (s *FileSnapshot) ResetEncodeOptions()
- func (s *FileSnapshot) VersionMadeBy() uint16
- func (s *FileSnapshot) VersionNeededToExtract() uint16
- type FileSortStrategy
- type Filter
- type ProgressStats
- type ResourceLimits
- type SecuritySettings
- type Sink
- type Source
- type StreamOption
- type StreamReader
- func (sr *StreamReader) ExtractFile(fpath string) error
- func (sr *StreamReader) ExtractTo(destDir string) error
- func (sr *StreamReader) ExtractToWithContext(ctx context.Context, destDir string) error
- func (sr *StreamReader) Next() (*File, error)
- func (sr *StreamReader) Open() (io.ReadCloser, error)
- func (sr *StreamReader) OpenRaw() (io.Reader, error)
- func (sr *StreamReader) RegisterDecompressor(method CompressionMethod, d Decompressor)
- func (sr *StreamReader) Scan(pattern string) (*File, error)
- func (sr *StreamReader) SetPassword(pwd string)
- func (sr *StreamReader) SetTextDecoder(td TextDecoder)
- type TextDecoder
- type TransformFunc
- type Zip
- func (z *Zip) Add(f *File, opts ...AddOption) error
- func (z *Zip) AddBytes(data []byte, filename string, opts ...AddOption) (*File, error)
- func (z *Zip) AddDir(path string, opts ...AddOption) ([]*File, error)
- func (z *Zip) AddFS(fileSystem fs.FS, opts ...AddOption) ([]*File, error)
- func (z *Zip) AddFile(path string, opts ...AddOption) (*File, error)
- func (z *Zip) AddLazy(name string, openFunc func() (io.ReadCloser, error), opts ...AddOption) (*File, error)
- func (z *Zip) AddOSFile(f *os.File, opts ...AddOption) (*File, error)
- func (z *Zip) AddReader(r io.Reader, filename string, size int64, opts ...AddOption) (*File, error)
- func (z *Zip) AddString(content string, filename string, opts ...AddOption) (*File, error)
- func (z *Zip) Config() ZipConfig
- func (z *Zip) Exists(name string) bool
- func (z *Zip) ExtractTo(path string, opts ...ZipOption) error
- func (z *Zip) ExtractToWithContext(ctx context.Context, path string, opts ...ZipOption) error
- func (z *Zip) FS() fs.FS
- func (z *Zip) File(name string) (*File, bool)
- func (z *Zip) Files() []*File
- func (z *Zip) Find(pattern string) ([]*File, error)
- func (z *Zip) Glob(pattern string) ([]*File, error)
- func (z *Zip) Load(src io.ReaderAt, size int64) ([]*File, error)
- func (z *Zip) LoadFromFile(f *os.File) ([]*File, error)
- func (z *Zip) LoadFromFileWithContext(ctx context.Context, f *os.File) ([]*File, error)
- func (z *Zip) LoadWithContext(ctx context.Context, src io.ReaderAt, size int64) ([]*File, error)
- func (z *Zip) Mkdir(name string, opts ...AddOption) (*File, error)
- func (z *Zip) Move(old, newDir string) error
- func (z *Zip) OpenFile(name string) (io.ReadCloser, error)
- func (z *Zip) RegisterCompressor(method CompressionMethod, factory CompressorFactory) *Zip
- func (z *Zip) RegisterDecompressor(method CompressionMethod, d Decompressor) *Zip
- func (z *Zip) Remove(name string) ([]*File, error)
- func (z *Zip) Rename(old, newName string) error
- func (z *Zip) Select(filters ...Filter) []*File
- func (z *Zip) SetConfig(c ZipConfig) *Zip
- func (z *Zip) Verify(opts ...ZipOption) error
- func (z *Zip) VerifyWithContext(ctx context.Context, opts ...ZipOption) error
- func (z *Zip) WriteHTTP(w http.ResponseWriter, filename string, opts ...ZipOption) error
- func (z *Zip) WriteHTTPWithContext(ctx context.Context, w http.ResponseWriter, filename string, opts ...ZipOption) error
- func (z *Zip) WriteTo(dest io.Writer, opts ...ZipOption) (int64, error)
- func (z *Zip) WriteToWithContext(ctx context.Context, dest io.Writer, opts ...ZipOption) (int64, error)
- type ZipConfig
- type ZipOption
- func WithExcludeDir(dirPath string) ZipOption
- func WithFilter(f Filter) ZipOption
- func WithFromDir(dirPath string) ZipOption
- func WithOnFileDone(fn func(*File, error)) ZipOption
- func WithOnly(files []*File) ZipOption
- func WithOpPassword(pwd string) ZipOption
- func WithProgress(cb func(ProgressStats)) ZipOption
- func WithSecurity(settings SecuritySettings) ZipOption
- func WithSmartStore(exts ...string) ZipOption
- func WithWorkers(n int) ZipOption
- type ZipStrategy
Constants ¶
const ( DeflateNormal = flate.DefaultCompression // -1 DeflateMaximum = flate.BestCompression // 9 DeflateFast = 3 DeflateSuperFast = flate.BestSpeed // 1 (Same as Fast in stdlib) DeflateStore = flate.NoCompression // 0 )
Compression levels for DEFLATE algorithm.
const ( // LatestZipVersion represents the maximum ZIP specification version supported // by this implementation. Version 63 corresponds to ZIP 6.3 specification. LatestZipVersion uint16 = 63 // StandardSizeLimit determines the maximum file size standard zip can store. // If this value is exceeded, the Zip64 format must be used. StandardSizeLimit = internal.MaxUint32 // StandardEntriesLimit determines the maximum number of files standard zip can store. // If this value is exceeded, the Zip64 EOCD and locator must be used. StandardEntriesLimit = internal.MaxUint16 // MaxStringLength determines the maximum length for filename and comment. MaxStringLength = internal.MaxUint16 // ExtraFieldLimit determines the maximum extra field length the zip can hold. ExtraFieldLimit = internal.MaxUint16 // Zip64ExtraFieldTag identifies the extra field that contains 64-bit size // and offset information for files exceeding 4GB limits. Zip64ExtraFieldTag = internal.Zip64ExtraFieldTag // NTFSFieldTag identifies the extra field that stores high-precision // NTFS file timestamps with 100-nanosecond resolution. NTFSFieldTag = internal.NTFSFieldTag // AESEncryptionTag identifies the extra field for WinZip AES encryption metadata, // including encryption strength and actual compression method. AESEncryptionTag = internal.AESEncryptionTag )
Constants defining ZIP format structure and special tag values
const SizeUnknown int64 = -1
SizeUnknown is a sentinel value used when the data size cannot be determined before writing (e.g., streaming from io.Reader).
Variables ¶
var ( // ErrFormat is returned when the input is not a valid ZIP archive. ErrFormat = errors.New("zip: not a valid zip file") // ErrNotImplemented is returned if this code path is not implemented. ErrNotImplemented = errors.New("zip: not implemented") )
Global errors
var ( // ErrFileEntry is returned when an invalid argument is passed to File creation. ErrFileEntry = errors.New("not a valid file entry") // ErrAlgorithm is returned when a compression algorithm is not supported. ErrAlgorithm = errors.New("unsupported compression algorithm") // ErrPasswordMismatch is returned when the provided password does not match // or when a password is required but not provided. ErrPasswordMismatch = errors.New("invalid password") // ErrChecksum is returned when reading a file checksum does not match. ErrChecksum = errors.New("checksum error") // ErrSizeMismatch is returned when the uncompressed size does not match the header. ErrSizeMismatch = errors.New("uncompressed size mismatch") // ErrFileNotFound is returned when the requested file is not found in the archive. // It wraps fs.ErrNotExist so it can be checked with os.IsNotExist. ErrFileNotFound = fmt.Errorf("file not found: %w", fs.ErrNotExist) // ErrInsecurePath is returned when a file path is invalid or attempts directory traversal (Zip Slip). ErrInsecurePath = errors.New("insecure file path") // ErrDuplicateEntry is returned when attempting to add a file with a name that already exists. ErrDuplicateEntry = errors.New("duplicate file name") // ErrFilenameTooLong is returned when a filename exceeds 65535 bytes. ErrFilenameTooLong = errors.New("filename too long") // ErrCommentTooLong is returned when a file comment exceeds 65535 bytes. ErrCommentTooLong = errors.New("comment too long") // ErrExtraFieldTooLong is returned when the total size of extra fields exceeds 65535 bytes. ErrExtraFieldTooLong = errors.New("extra field too long") // ErrResourceLimit is returned when extraction uses too much resources. ErrResourceLimit = errors.New("resource limit exceeded") )
File errors
var DefaultArchiver = NewArchiver( WithZipConfig(ZipConfig{ CompressionMethod: Deflate, CompressionLevel: DeflateNormal, FileSortStrategy: SortZIP64Optimized, }), )
var DefaultStoreExtensions = map[string]struct{}{
"7z": {}, "aar": {}, "ace": {}, "apk": {}, "arc": {}, "arj": {},
"br": {}, "bz2": {}, "cab": {}, "deb": {}, "dmg": {}, "epub": {},
"gz": {}, "jar": {}, "lz4": {}, "lzma": {}, "lzo": {}, "rar": {},
"rpm": {}, "tar": {}, "tgz": {}, "war": {}, "xz": {}, "zip": {},
"zst": {},
"mp4": {}, "mkv": {}, "avi": {}, "mov": {}, "webm": {},
"jpg": {}, "jpeg": {}, "png": {}, "gif": {}, "webp": {},
"mp3": {}, "ogg": {}, "flac": {},
"pdf": {}, "docx": {}, "xlsx": {}, "pptx": {},
}
DefaultStoreExtensions is an extended list of formats that are already compressed and do not require reprocessing.
Functions ¶
func ArchiveDir ¶ added in v1.4.0
ArchiveDir recursively adds contents of the directory to the archive and writes it to dest. See Archiver.ArchiveDir.
func ArchiveFiles ¶ added in v1.4.0
ArchiveFiles adds files to the archive and writes it to dest. See Archiver.ArchiveFiles.
func Clone ¶ added in v1.4.0
Clone copies archive with options using the default archiver. See Archiver.Clone.
func DecodeCP437 ¶ added in v1.2.0
DecodeCP437 converts CP437 (US DOS) string to UTF-8. This is the default fallback for ZIP archives.
func DecodeIBM866 ¶
DecodeIBM866 converts CP866 (Cyrillic DOS) string to UTF-8.
func Exists ¶ added in v1.4.0
Exists checks file existence. See Archiver.Exists.
func IsEncrypted ¶ added in v1.4.0
IsEncrypted checks encryption using the default archiver. See Archiver.IsEncrypted.
func IsZipStream ¶ added in v1.4.0
IsZipStream checks if the data stream starts with the ZIP local header signature. This is a necessary condition for StreamReader to work, as it cannot scan the file for the central directory.
func Merge ¶ added in v1.4.0
Merge combines archives using the default archiver. See Archiver.Merge.
func ReadFile ¶ added in v1.4.0
ReadFile reads file content using the default archiver. See Archiver.ReadFile.
func ReplaceFile ¶ added in v1.4.0
ReplaceFile replaces a file. See Archiver.ReplaceFile
func SafePath ¶ added in v1.4.0
SafePath returns a clean, absolute path for a zip entry within the destination directory. It ensures that the resulting path is inside the destDir (prevents Zip Slip).
func TotalSize ¶ added in v1.4.0
TotalSize calculates sizes using the default archiver. See Archiver.TotalSize.
func Transform ¶ added in v1.4.0
func Transform(zip Source, dest Sink, fn TransformFunc, opts ...ZipOption) error
Transform modifies files on the fly. See Archiver.Transform
func Tree ¶ added in v1.4.0
Tree returns a string representation of the archive structure. See Archiver.Tree.
func Unzip ¶ added in v1.4.0
Unzip opens source zip and extracts its contents to dest directory. See Archiver.Unzip.
func UnzipFile ¶ added in v1.4.0
UnzipFile extracts the specified file from the archive. See Archiver.UnzipFile.
func UnzipGlob ¶ added in v1.4.0
UnzipGlob extracts all files file whose name matches the path.Match pattern. See Archiver.UnzipGlob.
func UnzipToMap ¶ added in v1.4.0
UnzipToMap loads archive content into memory. See Archiver.UnzipToMap.
func UnzipToTemp ¶ added in v1.4.0
func UnzipToTemp(zip Source, prefix string, opts ...ZipOption) (path string, cleanup func(), err error)
UnzipToTemp extracts to a temp dir. See Archiver.UnzipToTemp.
func UpdateMetadata ¶ added in v1.4.0
UpdateMetadata modifies attributes. See Archiver.UpdateMetadata.
func UseSink ¶ added in v1.4.0
UseSink creates the destination writer and ensures it is closed properly.
func UseSource ¶ added in v1.4.0
UseSource opens the source, handles the ReaderAt vs Reader distinction, and ensures resources are closed properly after fn executes.
It passes:
- r: The underlying stream (always non-nil).
- rAt: The Random Access interface (non-nil if supported, e.g. File or Memory).
- size: The total size (or SizeUnknown).
func Verify ¶ added in v1.4.0
Verify checks the integrity of the archive. See Archiver.Verify.
Types ¶
type AddOption ¶
type AddOption func(f *File)
AddOption is a functional option for configuring file entries during addition.
func WithCompression ¶
func WithCompression(c CompressionMethod, lvl int) AddOption
WithCompression sets the compression method and level for a regular file. Ignored for directories.
func WithConfig ¶
func WithConfig(c FileConfig) AddOption
WithConfig applies a complete FileConfig, overwriting existing settings.
func WithEncryption ¶
func WithEncryption(e EncryptionMethod, pwd string) AddOption
WithEncryption sets the encryption method and password for a regular file. Ignored for directories.
func WithMarkDirsImplicit ¶ added in v1.4.0
func WithMarkDirsImplicit() AddOption
WithMarkDirsImplicit marks added directories as implicit.
func WithName ¶
WithName overrides the destination filename within the archive. The name is automatically normalized to use forward slashes.
func WithPassword ¶ added in v1.3.0
WithPassword sets the encryption password for a specific file. If no encryption method is specified, it defaults to AES256. Ignored for directories.
type ArchiveDiff ¶ added in v1.4.0
type ArchiveDiff struct {
Added []string // Files present only in B.
Removed []string // Files present only in A.
Modified []string // Files with differing CRCs or sizes.
}
ArchiveDiff describes the differences between two archives.
func Diff ¶ added in v1.4.0
func Diff(srcA, srcB Source, filters ...Filter) (ArchiveDiff, error)
Diff compares archives. See Archiver.Diff
type ArchiveOption ¶ added in v1.4.0
type ArchiveOption func(*Zip)
ArchiveOption is a function option for configuring archive creation
func WithCompressor ¶ added in v1.4.0
func WithCompressor(method CompressionMethod, factory CompressorFactory) ArchiveOption
WithCompressor registers a custom compression algorithm for this archive instance.
func WithDecompressor ¶ added in v1.4.0
func WithDecompressor(method CompressionMethod, d Decompressor) ArchiveOption
WithDecompressor registers a custom decompression algorithm.
func WithImplicitDirs ¶ added in v1.4.0
func WithImplicitDirs() ArchiveOption
WithImplicitDirs enables writing implicit dirs to the resulting archive.
func WithStrategy ¶ added in v1.4.0
func WithStrategy(s ZipStrategy) ArchiveOption
WithStrategy sets the parallel write strategy for the archive.
func WithZipCompression ¶ added in v1.4.0
func WithZipCompression(c CompressionMethod, lvl int) ArchiveOption
WithCompression sets the compression method and level for a regular file.
func WithZipConfig ¶ added in v1.4.0
func WithZipConfig(cfg ZipConfig) ArchiveOption
WithZipConfig applies the complete ZipConfig to the archive.
func WithZipEncryption ¶ added in v1.4.0
func WithZipEncryption(e EncryptionMethod, pwd string) ArchiveOption
WithPassword sets the encryption password for the archive.
func WithZipPassword ¶ added in v1.4.0
func WithZipPassword(pwd string) ArchiveOption
WithArchivePasswords sets global password for the archive. If no encryption method is specified, it defaults to AES256.
type Archiver ¶ added in v1.4.0
type Archiver struct {
// contains filtered or unexported fields
}
Archiver provides a configurable environment for working with ZIP archives. It is build on top of Zip and reduces boilerplate code for common operations. By default, it supports the Store (no compression) and Deflate compression methods.
func NewArchiver ¶ added in v1.4.0
func NewArchiver(opts ...ArchiveOption) *Archiver
NewArchiver creates a new Archiver instance build on top of Zip with the specified options.
func (*Archiver) ArchiveDir ¶ added in v1.4.0
ArchiveDir recursively archives the contents of a directory. By default: Deflate compression, relative paths are preserved.
func (*Archiver) ArchiveDirWithContext ¶ added in v1.4.0
func (a *Archiver) ArchiveDirWithContext(ctx context.Context, srcDir string, destZip Sink, opts ...ZipOption) error
ArchiveDirWithContext recursively adds contents of the directory with context support. Cancelling the context stops processing remaining files and closes the destination file.
func (*Archiver) ArchiveFiles ¶ added in v1.4.0
ArchiveFiles archives a list of files. File paths are "flattened" and placed in the root of the archive.
func (*Archiver) ArchiveFilesWithContext ¶ added in v1.4.0
func (a *Archiver) ArchiveFilesWithContext(ctx context.Context, files []string, destZip Sink, opts ...ZipOption) error
ArchiveFilesWithContext creates an archive from a list of files with context support.
func (*Archiver) Clone ¶ added in v1.4.0
Clone copies the archive with the possibility of applying filters or modifiers. Example: deleting files, changing compression. Returns ErrNotImplemented if source is io.Reader.
func (*Archiver) CloneWithContext ¶ added in v1.4.0
func (a *Archiver) CloneWithContext(ctx context.Context, zip Source, destZip Sink, opts ...ZipOption) error
CloneWithContext copies archive with context support.
func (*Archiver) Diff ¶ added in v1.4.0
func (a *Archiver) Diff(srcA, srcB Source, filters ...Filter) (ArchiveDiff, error)
Diff compares two archives and returns the differences.
func (*Archiver) DiffWithContext ¶ added in v1.4.0
func (a *Archiver) DiffWithContext(ctx context.Context, zipA, zipB Source, filters ...Filter) (diff ArchiveDiff, err error)
DiffWithContext compares two archives and returns the differences with context support.
func (*Archiver) ExistsWithContext ¶ added in v1.4.0
func (a *Archiver) ExistsWithContext(ctx context.Context, zip Source, filename string) (bool, error)
ExistsWithContext checks if a file exists with context support.
func (*Archiver) GetEntries ¶ added in v1.4.0
GetEntries returns a list of files in the archive without loading their contents. If source is io.Reader, the returned files cannot be opened.
func (*Archiver) GetEntriesWithContext ¶ added in v1.4.0
GetEntriesWithContext lists files with context support.
func (*Archiver) IsEncrypted ¶ added in v1.4.0
IsEncrypted checks if the archive contains at least one encrypted file.
func (*Archiver) Merge ¶ added in v1.4.0
Merge combines multiple archives into one. Conflict resolution strategy: "the last written file wins". Returns ErrNotImplemented if source is io.Reader.
func (*Archiver) MergeWithContext ¶ added in v1.4.0
MergeWithContext combines archives with context support.
func (*Archiver) ReadFile ¶ added in v1.4.0
ReadFile reads the contents of a file from the archive into a byte slice.
func (*Archiver) ReadFileWithContext ¶ added in v1.4.0
func (a *Archiver) ReadFileWithContext(ctx context.Context, zip Source, filename string) ([]byte, error)
ReadFileWithContext reads file content with context support. Cancelling the context stops the reading process.
func (*Archiver) ReplaceFile ¶ added in v1.4.0
ReplaceFile replaces a file in the archive with new content. The other files are copied without changes.
func (*Archiver) ReplaceFileWithContext ¶ added in v1.4.0
func (a *Archiver) ReplaceFileWithContext(ctx context.Context, zip Source, dest Sink, filename string, content io.Reader) error
ReplaceFileWithContext replaces a file in the archive with new content with context support.
func (*Archiver) Search ¶ added in v1.4.0
Search searches for text within the contents of all files in the archive. It returns a list of files containing the text. Warning: this is a resource-intensive operation, as it unpacks each file.
func (*Archiver) SearchWithContext ¶ added in v1.4.0
func (a *Archiver) SearchWithContext(ctx context.Context, zip Source, text string, filters ...Filter) ([]*File, error)
SearchWithContext scans content with context support.
func (*Archiver) TotalSize ¶ added in v1.4.0
func (a *Archiver) TotalSize(zip Source, filters ...Filter) (uncompressed, compressed int64, err error)
TotalSize returns the total size of compressed and uncompressed data in the archive.
func (*Archiver) Transform ¶ added in v1.4.0
Transform applies a function to each file in the archive, allowing modification of content. Example: Replace all occurrences of "old" with "new" in text files:
err := archive.Transform(src, dest, func(f *File) (io.Reader, error) {
if strings.HasSuffix(f.Name(), ".txt") {
return strings.NewReader(strings.ReplaceAll(f.Content(), "old", "new")), nil
}
return nil, nil // Keep original content
})
Returns ErrNotImplemented if source is io.Reader.
func (*Archiver) TransformWithContext ¶ added in v1.4.0
func (a *Archiver) TransformWithContext(ctx context.Context, zip Source, dest Sink, fn TransformFunc, opts ...ZipOption) error
TransformWithContext applies a function to each file in the archive, allowing modification of content with context support.
func (*Archiver) Tree ¶ added in v1.4.0
Tree returns a text representation of the archive structure (similar to the `tree` command).
func (*Archiver) TreeWithContext ¶ added in v1.4.0
func (a *Archiver) TreeWithContext(ctx context.Context, zip Source, filters ...Filter) (string, error)
Tree returns a string representation of the archive structure with context support.
func (*Archiver) Unzip ¶ added in v1.4.0
Unzip extracts the archive to the specified directory. If source is io.Reader, zip options do not apply.
func (*Archiver) UnzipFile ¶ added in v1.4.0
UnzipFile extracts the specified file from the archive.
func (*Archiver) UnzipFileWithContext ¶ added in v1.4.0
func (a *Archiver) UnzipFileWithContext(ctx context.Context, zip Source, filename string, dest Sink) error
UnzipFileWithContext extracts the specified file from the archive with context support.
func (*Archiver) UnzipGlob ¶ added in v1.4.0
UnzipGlob extracts all files file whose name matches the path.Match pattern.
func (*Archiver) UnzipGlobWithContext ¶ added in v1.4.0
func (a *Archiver) UnzipGlobWithContext(ctx context.Context, zip Source, pattern, destDir string) (err error)
UnzipGlobWithContext extracts all files file whose name matches the path.Match pattern with context support.
func (*Archiver) UnzipToMap ¶ added in v1.4.0
UnzipToMap extracts all files from the archive into a map[filename]content. Directories are ignored.
func (*Archiver) UnzipToMapWithContext ¶ added in v1.4.0
func (a *Archiver) UnzipToMapWithContext(ctx context.Context, zip Source, filters ...Filter) (map[string][]byte, error)
UnzipToMap extracts all files from the archive into a map[filename]content with context support.
func (*Archiver) UnzipToTemp ¶ added in v1.4.0
func (a *Archiver) UnzipToTemp(zip Source, prefix string, opts ...ZipOption) (path string, cleanup func(), err error)
UnzipToTemp unpacks the archive into a temporary directory. It returns the path and a cleanup function. It is the caller's responsibility to call cleanup().
func (*Archiver) UnzipToTempWithContext ¶ added in v1.4.0
func (a *Archiver) UnzipToTempWithContext(ctx context.Context, zip Source, prefix string, opts ...ZipOption) (path string, cleanup func(), err error)
UnzipToTempWithContext extracts the archive to a temporary directory with cancellation support.
func (*Archiver) UnzipWithContext ¶ added in v1.4.0
func (a *Archiver) UnzipWithContext(ctx context.Context, zip Source, destDir string, opts ...ZipOption) error
UnzipWithContext extracts archive contents with context support. Cancelling the context stops the extraction immediately.
func (*Archiver) UpdateMetadata ¶ added in v1.4.0
func (a *Archiver) UpdateMetadata(zip Source, dest Sink, modifier func(*File), opts ...ZipOption) error
UpdateMetadata modifies the metadata of files in the archive. Example: normalizing access permissions, adding comments. Returns ErrNotImplemented if source is io.Reader.
func (*Archiver) UpdateMetadataWithContext ¶ added in v1.4.0
func (a *Archiver) UpdateMetadataWithContext(ctx context.Context, zip Source, dest Sink, modifier func(*File), opts ...ZipOption) error
UpdateMetadataWithContext allows bulk modification with context support.
func (*Archiver) Verify ¶ added in v1.4.0
Verify checks the integrity of the files in the archive (CRC, checksums). If source is io.Reader, zip options do not apply.
func (*Archiver) VerifyWithContext ¶ added in v1.4.0
Verify checks the integrity of the files in the archive with context support.
type CompressionMethod ¶
type CompressionMethod uint16
CompressionMethod represents the compression algorithm used for a file in the ZIP archive
const ( Store CompressionMethod = 0 // No compression - file stored as-is Deflate CompressionMethod = 8 // DEFLATE compression (most common) Deflate64 CompressionMethod = 9 // DEFLATE64(tm) - Not supported natively BZIP2 CompressionMethod = 12 // BZIP2 - Not supported natively LZMA CompressionMethod = 14 // LZMA - Not supported natively ZStandard CompressionMethod = 93 // Zstandard - Not supported natively )
Supported compression methods according to ZIP specification. Note: This library natively supports Store (0) and Deflate (8). Other methods require registering custom compressors via RegisterCompressor.
type Compressor ¶
type Compressor interface {
// Compress reads from src and writes compressed data to dest.
// Returns the number of uncompressed bytes read.
Compress(src io.Reader, dest io.Writer) (int64, error)
}
Compressor transforms raw data into compressed data.
func NewDeflateCompressor ¶
func NewDeflateCompressor(level int) Compressor
NewDeflateCompressor creates a reusable compressor for a specific level.
type CompressorFactory ¶ added in v1.2.0
type CompressorFactory func(level int) Compressor
CompressorFactory creates a Compressor instance for a specific compression level. The level parameter is typically 0-9, but interpretations vary by algorithm. Implementations should normalize invalid levels to defaults.
type ConflictAction ¶ added in v1.4.0
type ConflictAction int
ConflictAction defines the decision taken when a file name collision occurs during Zip.Load.
const ( // ActionReplace overwrites the existing entry with the new one (Default). ActionReplace ConflictAction = iota // ActionSkip ignores the new entry, keeping the existing one. ActionSkip // ActionError reports [ErrDuplicateEntry] and skips the new entry. ActionError // ActionRename adds the new entry under a different name provided by the resolver. ActionRename )
func DefaultConflictHandler ¶ added in v1.4.0
func DefaultConflictHandler(_, _ *File) (ConflictAction, string)
DefaultConflictHandler replaces existing files (Last Write Wins).
func ErrorConflictHandler ¶ added in v1.4.0
func ErrorConflictHandler(_, _ *File) (ConflictAction, string)
ErrorConflictHandler treats duplicates as errors.
func SkipConflictHandler ¶ added in v1.4.0
func SkipConflictHandler(_, _ *File) (ConflictAction, string)
SkipConflictHandler keeps existing files and ignores new ones.
func UpdateConflictHandler ¶ added in v1.4.0
func UpdateConflictHandler(existing, new *File) (ConflictAction, string)
UpdateConflictHandler replaces the file only if the new one is newer (ModTime).
type ConflictHandler ¶ added in v1.4.0
type ConflictHandler func(existing, new *File) (ConflictAction, string)
ConflictHandler determines how to handle name collisions. It receives the existing file (already in archive) and the new file (being loaded). It returns the action to take and an optional new name (used only with ActionRename).
type Decompressor ¶
type Decompressor interface {
// Decompress returns a stream of uncompressed data.
Decompress(src io.Reader) (io.ReadCloser, error)
}
Decompressor transforms compressed data back into raw data.
type DeflateCompressor ¶
type DeflateCompressor struct {
// contains filtered or unexported fields
}
DeflateCompressor implements DEFLATE compression with memory pooling.
type DeflateDecompressor ¶
type DeflateDecompressor struct{}
DeflateDecompressor implements the "Deflate" method.
func (*DeflateDecompressor) Decompress ¶
func (dd *DeflateDecompressor) Decompress(src io.Reader) (io.ReadCloser, error)
type EncryptionMethod ¶
type EncryptionMethod uint16
EncryptionMethod represents the encryption algorithm used for file protection.
Compatibility Warning:
- AES256 is the recommended standard for security. It is supported by modern archivers like 7-Zip, WinRAR.
- Some legacy tools (e.g., older built-in macOS Archive Utility or Windows Explorer) may only support ZipCrypto (weak encryption). Use ZipCrypto only if legacy compatibility is strictly required.
const ( NotEncrypted EncryptionMethod = 0 // No encryption - file stored in plaintext ZipCrypto EncryptionMethod = 1 // Legacy encryption. Vulnerable to brute force attacks AES256 EncryptionMethod = 2 // Modern AES256 encryption )
Supported encryption methods
type File ¶
type File struct {
// contains filtered or unexported fields
}
File represents a file entry within a ZIP archive, encapsulating both metadata and content access mechanisms. Each File object corresponds to one entry in the ZIP central directory and can represent either a regular file or a directory.
func GetEntries ¶ added in v1.4.0
GetEntries lists files using the default archiver. Archiver.GetEntries
func NewFile ¶ added in v1.4.0
NewFile creates a detached File entry with manual metadata. Note: The file is not attached to any archive until you call Zip.Add. You must set a data source via File.WithOpenFunc before writing, unless it's a directory.
func Search ¶ added in v1.4.0
Search grep content. See Archiver.Search.
func SortFilesOptimized ¶
func SortFilesOptimized(files []*File, strategy FileSortStrategy) []*File
SortFilesOptimized returns a sorted slice of files according to the strategy. Returns a new slice; the original slice is not modified.
func (*File) CompressedSize ¶
CompressedSize returns the size of the compressed data within the archive.
func (*File) Config ¶ added in v1.1.0
func (f *File) Config() FileConfig
Config returns archive file entry configuration.
func (*File) FillSnapshot ¶ added in v1.4.0
func (f *File) FillSnapshot(snap *FileSnapshot)
FillSnapshot executes the passed data snapshot to avoid allocations.
func (*File) FsTime ¶ added in v1.1.0
FsTime returns the file timestamps (Modification, Access, Creation) if available.
func (*File) GetExtraField ¶
GetExtraField retrieves the raw bytes of an extra field by its tag ID.
func (*File) HasExtraField ¶
HasExtraField checks whether an extra field with the specified tag exists.
func (*File) HostSystem ¶ added in v1.1.0
func (f *File) HostSystem() sys.HostSystem
HostSystem returns the system file was created in.
func (*File) IsEncrypted ¶ added in v1.4.0
IsEncrypted checks wether the data from the original archive is encrypted.
func (*File) IsImplicit ¶ added in v1.4.0
IsImplicit returns true if the entry was created automatically and is not associated with a real directory.
func (*File) LocalHeaderOffset ¶ added in v1.4.0
LocalHeaderOffset returns file entry offset inside the archive.
func (*File) Open ¶
func (f *File) Open() (io.ReadCloser, error)
Open returns an io.ReadCloser for reading the uncompressed content of the file. If the file comes from an existing archive, the source config is used.
Returns an error if the file is a directory or has no data source. ErrPasswordMismatch is returned immediately if the provided password is incorrect. The returned ReadCloser may return ErrChecksum during reading (typically at EOF) or upon Close() if the data integrity check fails.
func (*File) OpenRaw ¶ added in v1.4.0
func (f *File) OpenRaw() (*io.SectionReader, error)
OpenRaw returns an io.SectionReader for reading the raw file content (compressed and/or encrypted) directly from the archive source. If the file is encrypted (AES), the reader includes Salt, PVV, and MAC bytes. Returns error if the file source is not available.
func (*File) RequiresZip64 ¶
RequiresZip64 determines whether this file requires ZIP64 format extensions.
func (*File) SetExtraField ¶
SetExtraField adds or replaces an extra field entry for this file. Returns an error if adding the field would exceed the maximum extra field length.
func (*File) Snapshot ¶ added in v1.4.0
func (f *File) Snapshot() *FileSnapshot
Snapshot creates an immutable copy of the file's metadata.
func (*File) UncompressedSize ¶
UncompressedSize returns the size of the original file content before compression.
func (*File) WithComment ¶ added in v1.4.0
func (*File) WithCompression ¶ added in v1.4.0
func (f *File) WithCompression(method CompressionMethod, level int) *File
WithCompression replaces the compression method and level with the specified ones. This does not affect configuration for decompressing file from an existing archive.
func (*File) WithConfig ¶ added in v1.4.0
func (f *File) WithConfig(c FileConfig) *File
WithConfig applies a FileConfig to this file, overriding individual properties.
func (*File) WithDisableEncryption ¶ added in v1.4.0
WithDisableEncryption sets encryption method to NotEncrypted and removes the password for this file. This does not affect configuration for decompressing file from an existing archive.
func (*File) WithEncryption ¶ added in v1.4.0
func (f *File) WithEncryption(method EncryptionMethod, pwd string) *File
WithEncryption replaces the encryption method and password with the specified ones. This does not affect configuration for decompressing file from an existing archive.
func (*File) WithModTime ¶ added in v1.4.0
WithModTime sets the file's last modification time.
func (*File) WithOpenFunc ¶ added in v1.4.0
func (f *File) WithOpenFunc(openFunc func() (io.ReadCloser, error)) *File
WithOpenFunc replaces the function used to open the file's content.
func (*File) WithPassword ¶ added in v1.4.0
SetSourcePassword updates the password used to encrypt/decrypt this specific file. If current encryption is NotEncrypted it defaults to AES256.
func (*File) WithSourcePassword ¶ added in v1.4.0
WithSourcePassword updates the password used to read (decrypt) this specific file from the original archive in case if the archive-wide password was incorrect or if different files have different passwords.
func (*File) WithUncompressedSize ¶ added in v1.4.0
SetUncompressed size sets the file uncompressed size atomically.
type FileConfig ¶
type FileConfig struct {
// CompressionMethod overrides the global default.
CompressionMethod CompressionMethod
// CompressionLevel overrides the global default.
CompressionLevel int
// EncryptionMethod overrides the global default.
EncryptionMethod EncryptionMethod
// Password overrides the global archive password for this file.
Password string
// Comment is a file-specific comment (max 65535 bytes).
Comment string
}
FileConfig defines configuration specific to a single archive entry. It overrides the global ZipConfig.
type FileError ¶ added in v1.4.0
type FileError struct {
Op string // Operation that failed (e.g., "open", "write", "extract")
File *File // The file entry that caused the error
Err error // The actual error (sentinel error)
}
FileError wraps an error with context about a specific file entry.
type FileSnapshot ¶ added in v1.4.0
type FileSnapshot struct {
Name string
IsDir bool
IsImplicit bool
Mode fs.FileMode
ModTime time.Time
HostSystem sys.HostSystem
// Configuration (Snapshot of FileConfig)
Config FileConfig
// State (Values read from atomics at the moment of snapshot)
UncompressedSize int64
CompressedSize int64
LocalHeaderOffset int64
CRC32 uint32
Flags uint16
// Extra Fields (Deep copy or flattened representation)
Metadata sys.Metadata
ExtraField map[uint16][]byte
ExtraFieldRaw []byte
// contains filtered or unexported fields
}
FileSnapshot represents an immutable point-in-time copy of File metadata.
func (*FileSnapshot) CentralDirectory ¶ added in v1.4.0
func (s *FileSnapshot) CentralDirectory() internal.CentralDirectory
CentralDirectory generates the central directory entry for this file.
func (*FileSnapshot) CompressionLevelBits ¶ added in v1.4.0
func (s *FileSnapshot) CompressionLevelBits() uint16
func (*FileSnapshot) CompressionMethod ¶ added in v1.4.0
func (s *FileSnapshot) CompressionMethod() uint16
func (*FileSnapshot) ExternalFileAttributes ¶ added in v1.4.0
func (s *FileSnapshot) ExternalFileAttributes() uint32
func (*FileSnapshot) FileBitFlag ¶ added in v1.4.0
func (s *FileSnapshot) FileBitFlag() uint16
func (*FileSnapshot) LocalHeader ¶ added in v1.4.0
func (s *FileSnapshot) LocalHeader() internal.LocalFileHeader
LocalHeader generates the local file header that precedes the file data.
func (*FileSnapshot) RequiresZip64 ¶ added in v1.4.0
func (s *FileSnapshot) RequiresZip64() bool
RequiresZip64 checks if Zip64 format is needed based on the snapshot values.
func (*FileSnapshot) ResetEncodeOptions ¶ added in v1.4.0
func (s *FileSnapshot) ResetEncodeOptions()
ResetEncodeOptions resets file encode options to default
func (*FileSnapshot) VersionMadeBy ¶ added in v1.4.0
func (s *FileSnapshot) VersionMadeBy() uint16
func (*FileSnapshot) VersionNeededToExtract ¶ added in v1.4.0
func (s *FileSnapshot) VersionNeededToExtract() uint16
type FileSortStrategy ¶
type FileSortStrategy int
FileSortStrategy defines the order in which files are written to the archive. Choosing the right strategy can optimize writing speed (CPU parallelism), memory usage or archive structure (ZIP64 overhead).
const ( SortDefault FileSortStrategy = iota SortLargeFilesLast // Large files (>=4GB) at end SortLargeFilesFirst // Large files (>=4GB) at start SortSizeAscending // Smallest first SortSizeDescending // Largest first SortZIP64Optimized // Buckets: <10MB, <4GB, >=4GB (each sorted Asc) SortAlphabetical // A-Z by filename )
type Filter ¶ added in v1.4.0
Filter filters out the files.
func FilterExcludeDir ¶ added in v1.4.0
FilterExcludeDir returns files without a provided directory and its contents.
func FilterFromDir ¶ added in v1.4.0
FilterFromDir returns only files nested under the specified path.
func FilterOnly ¶ added in v1.4.0
WithFiles returns files provided.
type ProgressStats ¶ added in v1.4.0
type ProgressStats struct {
CurrentFile *File // Currently processed file
CurrentRead int64 // Uncompressed bytes read from current file
CurrentWritten int64 // Bytes produced for current file
ExpectedRead int64 // Sum of uncompressed file sizes
TotalRead int64 // Total uncompressed bytes read so far
TotalWritten int64 // Total compressed bytes produced so far
ArchiveWritten int64 // Total bytes written to dest (headers + data + CD)
TotalFiles int64 // Total amount of files to process
ProcessedFiles int64 // The total number of files processed, including errors.
Errors int64 // Failed files count
}
ProgressStats contains detailed information about the current progress of the operation.
type ResourceLimits ¶ added in v1.4.0
type ResourceLimits struct {
// MaxTotalSize is the maximum allowed bytes to write to disk for the whole operation.
// Default: 0 (unlimited).
MaxTotalSize int64
// MaxFileSize is the maximum allowed size for a single file.
// Default: 0 (unlimited).
MaxFileSize int64
// MaxCompressionRatio is the maximum allowed ratio between uncompressed and compressed size.
// E.g., 100 means uncompressed data cannot be more than 100x larger than compressed.
// Default: 0 (disabled). Recommended: 100-200.
MaxRatio float64
}
ResourceLimits defines constraints for extraction.
type SecuritySettings ¶ added in v1.4.0
type SecuritySettings struct {
// AllowSymlinks enables extraction of symbolic links.
// WARNING: disabling this is recommended for untrusted archives.
// Default: false.
AllowSymlinks bool
// MinEncryption allows enforcing a minimum encryption standard.
// e.g. Require AES256 to prevent downgrade attacks.
MinEncryption EncryptionMethod
// ResourceLimits defines constraints for extraction.
ResourceLimits ResourceLimits
}
SecuritySettings define extraction safety configuration.
type Sink ¶ added in v1.4.0
Sink provides an interface for writing a ZIP archive. Implementations must support file creation and closing.
func ToFile ¶ added in v1.4.0
ToFile creates a Sink for writing to an open *os.File file. The file is not closed after the operation.
func ToFilePath ¶ added in v1.4.0
ToFilePath creates a Sink for writing to a file at the specified path.
func ToURL ¶ added in v1.4.0
ToURL creates a Sink that streams the generated ZIP archive directly to a URL. If method is empty, it defaults to http.MethodPut.
type Source ¶ added in v1.4.0
Source provides an interface for reading a ZIP archive. Implementations must support multiple reads (for example, via io.ReaderAt).
func FromFile ¶ added in v1.4.0
FromFile creates a Source from an opened *os.File file. The file is not closed after the operation.
func FromFilePath ¶ added in v1.4.0
FromFilePath creates a Source from a file at the specified path.
func FromReaderAt ¶ added in v1.4.0
FromReaderAt creates a Source from an io.ReaderAt with a known size.
func FromStream ¶ added in v1.4.0
FromStream creates source from an io.Reader with a known size.
type StreamOption ¶ added in v1.4.0
type StreamOption func(s *StreamReader)
StreamOption applies the option to StreamReader.
func WithStreamConfig ¶ added in v1.4.0
func WithStreamConfig(cfg ZipConfig) StreamOption
WithStreamConfig sets the stream config.
type StreamReader ¶ added in v1.4.0
type StreamReader struct {
// contains filtered or unexported fields
}
StreamReader reads a ZIP archive sequentially from an io.Reader.
Unlike the standard Zip struct (which requires io.ReaderAt), StreamReader does not need random access to the data source. This makes it ideal for processing ZIP archives from network streams (e.g., HTTP response bodies) or pipes without buffering the entire file to disk or memory.
Limitations:
- Since it reads Local File Headers instead of the Central Directory, metadata usually stored at the end of the archive is incomplete.
- You can only read files in the order they appear in the stream. You cannot go back to a previous file.
func NewStreamReader ¶ added in v1.4.0
func NewStreamReader(src io.Reader, opts ...StreamOption) *StreamReader
NewStreamReader returns a new StreamReader reading from source.
func (*StreamReader) ExtractFile ¶ added in v1.4.0
func (sr *StreamReader) ExtractFile(fpath string) error
func (*StreamReader) ExtractTo ¶ added in v1.4.0
func (sr *StreamReader) ExtractTo(destDir string) error
ExtractTo unpacks the archive to the specified destination directory. Attempts to extract files outside the target directory will result in ErrInsecurePath.
func (*StreamReader) ExtractToWithContext ¶ added in v1.4.0
func (sr *StreamReader) ExtractToWithContext(ctx context.Context, destDir string) error
ExtractToWithContext extracts files with context support. Context cancellation stops the extraction process.
func (*StreamReader) Next ¶ added in v1.4.0
func (sr *StreamReader) Next() (*File, error)
Next advances to the next entry in the ZIP archive. The CRC32 checksum is verified only after the stream is fully consumed.
Returns the next File entry or io.EOF if the end of the archive is reached. If the previous file's data was not fully read, Next automatically discards the remaining bytes to reach the next header. The returned file should not be opened manually, but rather using StreamReader.Open.
Warning: The returned File object is populated from the Local File Header. Fields like Unix permissions, file comments, or precise NTFS timestamps are unavailable.
func (*StreamReader) Open ¶ added in v1.4.0
func (sr *StreamReader) Open() (io.ReadCloser, error)
Open returns an io.ReadCloser that provides access to the decompressed content of the current file. It must be called after a successful StreamReader.Next and it be called only once per file. Closing the returned ReadCloser is optional for the library's internal state, but recommended to free resources immediately. Returns error if no file is currently selected.
func (*StreamReader) OpenRaw ¶ added in v1.4.0
func (sr *StreamReader) OpenRaw() (io.Reader, error)
OpenRaw returns an io.Reader for reading the raw content (compressed and/or encrypted) directly from the currently opened file. If the file is encrypted (AES256), the reader includes Salt, PVV, and MAC bytes.
func (*StreamReader) RegisterDecompressor ¶ added in v1.4.0
func (sr *StreamReader) RegisterDecompressor(method CompressionMethod, d Decompressor)
RegisterDecompressor adds support for reading a custom compression method. See DeflateDecompressor for implementation example.
func (*StreamReader) Scan ¶ added in v1.4.0
func (sr *StreamReader) Scan(pattern string) (*File, error)
Scan searches for the next file whose name matches the path.Match pattern. It automatically skips all intermediate files. Returns ErrFileNotFound if there are no more matches.
func (*StreamReader) SetPassword ¶ added in v1.4.0
func (sr *StreamReader) SetPassword(pwd string)
SetPassword sets current password atomically.
func (*StreamReader) SetTextDecoder ¶ added in v1.4.0
func (sr *StreamReader) SetTextDecoder(td TextDecoder)
SetTextDecoder sets current TextDecoder atomically.
type TextDecoder ¶
TextDecoder is a function that converts raw binary string (interpreted as specific encoding) into UTF-8.
type TransformFunc ¶ added in v1.4.0
TransformFunc defines the logic for modifying a file:
- (newReader, nil): replace the content;
- (nil, nil): leave unchanged;
- (nil, ErrSkip): delete the file.
type Zip ¶
type Zip struct {
// contains filtered or unexported fields
}
Zip represents an in-memory ZIP archive manager. It is concurrency-safe and supports streaming, random access, and parallel operations.
By default it supports Store (no compression) and Deflate compression methods.
func NewZip ¶
func NewZip(opts ...ArchiveOption) *Zip
NewZip creates a ready-to-use empty ZIP archive. Default support includes Store (No Compression) and Deflate.
func (*Zip) Add ¶ added in v1.4.0
Add adds a pre-configured File object to the archive. Paths are normalized to use forward slashes.
Unlike Zip.Load, add methods are strict: if a file with the same name already exists in the archive, they return ErrDuplicateEntry and do not overwrite the existing entry.
Options can be used to override compression, encryption, or file attributes.
func (*Zip) AddBytes ¶
AddBytes adds a file from a byte slice. Returns ErrFileEntry if an invalid argument is passed.
func (*Zip) AddDir ¶ added in v1.3.0
AddDir recursively adds contents of the directory to the archive. Files are added using "Best Effort" strategy: if a single file fails to read, AddDir continues processing others but returns a joined error at the end.
func (*Zip) AddFS ¶ added in v1.3.0
AddFS adds files from an fs.FS (e.g., embed.FS, os.DirFS) to the archive. It recursively walks the file system and adds all entries using "Best Effort" strategy.
func (*Zip) AddFile ¶
AddFile adds a file from the local filesystem to the archive. Symlinks are stored as link targets and are not followed.
func (*Zip) AddLazy ¶ added in v1.3.0
func (z *Zip) AddLazy(name string, openFunc func() (io.ReadCloser, error), opts ...AddOption) (*File, error)
AddLazy adds a file entry whose content is opened only when writing the archive.
The io.ReadCloser returned by openFunc is automatically closed by the library after the file is written. You do not need to wrap it to close it manually, but you are responsible for closing any resources used to create that reader (e.g. database connections) inside the closure or after Zip.WriteTo finishes.
Returns ErrFileEntry if an invalid name is passed.
func (*Zip) AddOSFile ¶ added in v1.2.0
AddOSFile adds an open os.File to the archive. The file content is wrapped using io.SectionReader.
func (*Zip) AddReader ¶
AddReader adds a file from an io.Reader stream.
If size is SizeUnknown and the target writer is an io.Seeker (e.g., os.File), the writer will buffer the entire stream to a temporary file to calculate headers before writing. To avoid this, provide the exact size if possible.
Returns ErrFileEntry if an invalid argument is passed.
func (*Zip) AddString ¶
AddString adds a file from a string. Returns ErrFileEntry if an invalid argument is passed.
func (*Zip) Exists ¶
Exists checks if a file or directory exists in the archive. Returns true if an exact file match is found.
func (*Zip) ExtractTo ¶ added in v1.4.0
ExtractTo unpacks the archive to the specified destination directory using "Best Effort" strategy. It automatically creates missing directory structures and restores file modification times and permissions. Attempts to extract files outside the target directory will result in ErrInsecurePath.
func (*Zip) ExtractToWithContext ¶ added in v1.4.0
ExtractToWithContext extracts files with context support. Context cancellation stops the extraction process.
func (*Zip) FS ¶ added in v1.3.0
FS returns fs.FS, a read-only virtual filesystem on top of the ZIP archive.
func (*Zip) File ¶ added in v1.2.0
File returns the entry matching the given name and wether it exists. Name is case-sensitive. Paths are normalized to use forward slashes.
func (*Zip) Find ¶ added in v1.2.0
Find searches for files matching the pattern in all directories. Unlike Glob, the pattern "*" matches "/" characters. Example: Find("*.log") matches "error.log" and "var/logs/access.log".
func (*Zip) Glob ¶ added in v1.2.0
Glob returns all files file whose name matches the path.Match pattern.
func (*Zip) Load ¶ added in v1.2.0
Load parses an existing ZIP archive's central directory and merges its entries into the current Zip instance using "Best Effort" strategy. It supports standard ZIP, Zip64, and archives with preambles (e.g., self-extracting EXEs).
If the current archive already contains entries with the same name as in the source, the existing entries are replaced by the new ones by default. You can change logic by specifying custom [ZipConfig.ConflictHandler].
Returns ErrFormat if the source is not a valid ZIP archive.
func (*Zip) LoadFromFile ¶ added in v1.2.0
LoadFromFile parses a ZIP from a local os.File.
func (*Zip) LoadFromFileWithContext ¶ added in v1.3.0
LoadFromFile parses a ZIP from a local os.File with context support.
func (*Zip) LoadWithContext ¶ added in v1.2.0
LoadWithContext parses an archive with context support. Cancelling the context stops processing the remaining files.
func (*Zip) Mkdir ¶ added in v1.2.0
Mkdir creates an explicit directory entry in the archive. Returns ErrFileEntry if invalid name is passed.
func (*Zip) Move ¶ added in v1.1.0
Move changes the directory location of an entry while preserving its base name. If target is a directory, the entire tree is moved recursively to the new location. Any missing parent directories in the destination path are automatically created. Example: Move("etc/file.txt", "backup/docs") -> "backup/docs/file.txt".
Like Zip.Rename, this operation is atomic. It validates all resulting child paths before modifying the archive structure.
Errors:
- Returns ErrFileNotFound if the old entry does not exist.
- Returns ErrDuplicateEntry if the destination path is already occupied.
- Returns ErrFilenameTooLong if any resulting path exceeds 65,535 bytes.
func (*Zip) OpenFile ¶
func (z *Zip) OpenFile(name string) (io.ReadCloser, error)
OpenFile returns a ReadCloser for the named file within the archive. Returns ErrFileNotFound if not found or target is a directory.
func (*Zip) RegisterCompressor ¶
func (z *Zip) RegisterCompressor(method CompressionMethod, factory CompressorFactory) *Zip
RegisterCompressor registers a factory function for a specific compression method. See NewDeflateCompressor for creating custom compressors.
func (*Zip) RegisterDecompressor ¶
func (z *Zip) RegisterDecompressor(method CompressionMethod, d Decompressor) *Zip
RegisterDecompressor adds support for reading a custom compression method. See DeflateDecompressor for creating custom decompressors.
func (*Zip) Remove ¶ added in v1.3.0
Remove deletes an entry from the archive. If the target is a directory, it recursively removes all its contents and the directory entry itself.
Providing an empty string or "." results in a "Reset" operation: all entries are removed, and the archive becomes empty.
Returns ErrFileNotFound if no entries matched the provided name.
func (*Zip) Rename ¶ added in v1.1.0
Rename changes the name of an entry while preserving its current directory location. If target is a directory, it recursively renames all nested files and subdirectories to reflect the new parent name. Example: Rename("logs/old.txt", "new.txt") -> "logs/new.txt"
This operation is atomic. It performs a "dry run" check of all resulting paths. If any path (including children) exceeds ZIP limits or conflicts with existing entries, no changes are applied to the archive.
Errors:
- Returns ErrFileEntry if the newName is empty or contains slashes.
- Returns ErrFileNotFound if the old entry does not exist.
- Returns ErrDuplicateEntry if the destination path is already occupied.
- Returns ErrFilenameTooLong if any resulting path exceeds 65,535 bytes.
func (*Zip) Select ¶ added in v1.4.0
Select returns a list of files that satisfy the given condition.
func (*Zip) SetConfig ¶
SetConfig updates the global configuration atomically. The current password is applied to all loaded files.
func (*Zip) Verify ¶ added in v1.4.0
Verify checks the integrity of the archive files. It decompresses every file and verifies checksums/MACs without writing to disk.
func (*Zip) VerifyWithContext ¶ added in v1.4.0
VerifyWithContext checks integrity with context cancellation.
func (*Zip) WriteHTTP ¶ added in v1.4.0
WriteHTTP writes the archive to the HTTP response writer with correct headers.
If an error occurs before writing data (e.g. empty archive), it does not write headers, allowing the caller to send an HTTP 500/400.
If an error occurs during writing, the download will be truncated/corrupted (which is the only way to signal failure to the client after headers are sent). In this case, the error is returned for server-side logging.
func (*Zip) WriteHTTPWithContext ¶ added in v1.4.0
func (*Zip) WriteTo ¶ added in v1.2.0
WriteTo serializes the archive to the specified writer. Files are processes using "Best Effort" strategy. If the writer is io.Seeker, temporary files are used if size exceeds [ZipConfig.MemoryThreshold]).
Use WithWorkers option to speed the compression significantly. Speed scales efficiently with CPU cores for compression-heavy tasks (Deflate/AES). Peak memory usage is strictly bounded by the pipeline capacity (maxWorkers * 2) and the MemoryThreshold (default 10MB).
Efficiency Note: Processing files in descending order of size (SortSizeDescending) helps finish long-running compression tasks early and can stabilize memory usage, though it may be slightly slower for small archives.
Returns the total number of bytes written or an error if the operation fails.
func (*Zip) WriteToWithContext ¶ added in v1.2.0
func (z *Zip) WriteToWithContext(ctx context.Context, dest io.Writer, opts ...ZipOption) (int64, error)
WriteToWithContext writes the archive with context support. Cancelling the context stops processing the remaining files and results in a valid archive.
type ZipConfig ¶
type ZipConfig struct {
// CompressionMethod is the default algorithm for new files.
CompressionMethod CompressionMethod
// CompressionLevel controls the speed vs size trade-off (0-9).
// 0 = Store (no compression), 9 = Best compression.
CompressionLevel int
// EncryptionMethod is the default encryption algorithm.
// Recommended: [AES256].
EncryptionMethod EncryptionMethod
// Password is the default credentials for encrypting the archive.
// If specified, defaults to [AES256] encryption.
Password string
// Comment is the archive-level comment (max 65535 bytes).
Comment string
// FileSortStrategy determines the order of file
// processing and their order in the written archive.
FileSortStrategy FileSortStrategy
// ZipStrategy determines what parallel write strategy to use. By default
// the order of files in the written archive is not deterministic.
ZipStrategy ZipStrategy
// ConflictHandler defines the strategy for handling
// duplicate file names during [Zip.Load]. If nil,
// defaults to [ActionReplace] (Last Write Wins).
ConflictHandler ConflictHandler
// TextDecoder handles filename decoding for legacy archives (non-UTF8).
// This function is only used in read operations. GoZip always sets
// the UTF-8 flag for maximum compatibility when writing.
// Default: [DecodeCP437] (IBM PC).
TextDecoder TextDecoder
// OnFileDone is a callback triggered after a file is written, read, or extracted.
// Errors are not wrapped in [FileError], because file instance is passed separately.
// This callback can be used to stop bulk operations on the first error.
//
// WARNING: This callback may be triggered concurrently if [WithWorkers] is used.
OnFileDone func(*File, error)
// MemoryThreshold determines the maximum file size in bytes that
// can be buffered in memory. If the file size exceeds this threshold,
// a temporary file will be used. The default value is 10 MB.
MemoryThreshold int64
// IncludeImplicitDirs determines whether to include implicitly
// created dirs in the resulting archive for saving specific metadata.
IncludeImplicitDirs bool
}
ZipConfig defines global configuration parameters for the archive. These settings apply to the entire archive but can be overridden per-file using FileConfig options.
type ZipOption ¶ added in v1.4.0
type ZipOption func(*processConfig)
ZipOption is a function option for configuring Zip operations.
func WithExcludeDir ¶ added in v1.4.0
WithExcludeDir excludes a directory and its contents from operation.
func WithFilter ¶ added in v1.4.0
WithFilter allows using any custom Filter as an option.
func WithFromDir ¶ added in v1.4.0
WithFromDir restricts operation to files nested under the specified path.
func WithOnFileDone ¶ added in v1.4.0
WithOnFileDone overrides global [ZipConfig.OnFileDone]
func WithOpPassword ¶ added in v1.4.0
WithOpPassword overwrites password for each file in the operation.
func WithProgress ¶ added in v1.4.0
func WithProgress(cb func(ProgressStats)) ZipOption
WithProgress adds a callback to monitor bytes in real time. If operation uses workers, this progress is called concurrently.
func WithSecurity ¶ added in v1.4.0
func WithSecurity(settings SecuritySettings) ZipOption
WithSecurity applies security settings for extraction.
func WithSmartStore ¶ added in v1.4.0
WithSmartStore disables compression for files whose extensions are in the list. Passed extensions are merged with DefaultStoreExtensions. This filter changes the state of File objects in the archive.
func WithWorkers ¶ added in v1.4.0
WithWorkers sets the given amount of workers for the operation.
type ZipStrategy ¶ added in v1.4.0
type ZipStrategy int
ZipStrategy determines the write strategy.
const ( StrategyPerformance ZipStrategy = iota // Maximum speed, order doesn't matter StrategyOrdered // Preserve the original file order )