package archive import ( "archive/zip" "fmt" "io/ioutil" "os" "path/filepath" ) type ZipArchiver struct { filepath string filewriter *os.File writer *zip.Writer } func NewZipArchiver(filepath string) Archiver { return &ZipArchiver{ filepath: filepath, } } func (a *ZipArchiver) ArchiveContent(content []byte, infilename string) error { if err := a.open(); err != nil { return err } defer a.close() f, err := a.writer.Create(infilename) if err != nil { return err } _, err = f.Write(content) return err } func (a *ZipArchiver) ArchiveFile(infilename string) error { fi, err := assertValidFile(infilename) if err != nil { return err } content, err := ioutil.ReadFile(infilename) if err != nil { return err } return a.ArchiveContent(content, fi.Name()) } func (a *ZipArchiver) ArchiveDir(indirname string) error { _, err := assertValidDir(indirname) if err != nil { return err } if err := a.open(); err != nil { return err } defer a.close() return filepath.Walk(indirname, func(path string, info os.FileInfo, err error) error { if info.IsDir() { return nil } if err != nil { return err } relname, err := filepath.Rel(indirname, path) if err != nil { return fmt.Errorf("error relativizing file for archival: %s", err) } f, err := a.writer.Create(relname) if err != nil { return fmt.Errorf("error creating file inside archive: %s", err) } content, err := ioutil.ReadFile(path) if err != nil { return fmt.Errorf("error reading file for archival: %s", err) } _, err = f.Write(content) return err }) } func (a *ZipArchiver) open() error { f, err := os.Create(a.filepath) if err != nil { return err } a.filewriter = f a.writer = zip.NewWriter(f) return nil } func (a *ZipArchiver) close() { if a.writer != nil { a.writer.Close() a.writer = nil } if a.filewriter != nil { a.filewriter.Close() a.filewriter = nil } }