go_zipper/gzip/compress.go

79 lines
1.7 KiB
Go

package gzip
import (
"compress/gzip"
"fmt"
"io"
"io/fs"
"os"
"strings"
zipper "git.sa-roci.de/oss/go_zipper"
)
const ArchiveExt = ".gz"
// NewZipper makes a new Zipper.
func NewGZipper(gzipFilename string, multiFile bool) zipper.Zipper {
if !strings.HasSuffix(strings.ToLower(gzipFilename), ArchiveExt) {
gzipFilename += ArchiveExt
}
gzipper := gZipper{
Zipper: zipper.NewBaseZipper(gzipFilename),
multiFile: multiFile,
}
gzipper.SetCompressor(&gzipper)
return gzipper
}
type gZipper struct {
zipper.Zipper
output io.Writer
multiFile bool
}
func (gz *gZipper) OpenWriter(zipFile *os.File) error {
gz.SetWriter(gzip.NewWriter(zipFile))
gz.output = zipFile
return nil
}
func (gz *gZipper) MultiFileSupported() bool {
return gz.multiFile
}
func (gz *gZipper) Compress(fileToZip *os.File, pathInArchive string) (err error) {
// Get the file information
var info fs.FileInfo
if info, err = fileToZip.Stat(); err != nil {
return err
}
filename := info.Name()
if writer, ok := gz.GetWriter().(*gzip.Writer); ok {
writer.ModTime = info.ModTime()
// Using FileInfoHeader() above only uses the basename of the file. If we want
// to preserve the folder structure we can overwrite this with the full path.
if len(pathInArchive) > 0 || strings.Contains(filename, "/") || strings.Contains(filename, "\\") {
writer.Name = zipper.PrependPath(filename, pathInArchive)
} else {
writer.Name = filename
}
if _, err = io.Copy(writer, fileToZip); err == nil {
flushErr := writer.Flush()
if err = writer.Close(); err != nil {
err = flushErr
} else {
writer.Reset(gz.output)
}
}
} else {
err = fmt.Errorf("unable to access compressor")
}
return
}