Skip to content

Instantly share code, notes, and snippets.

@devshorts
Created August 29, 2018 16:44
Show Gist options
  • Save devshorts/0b7cc8268adee6b1468d94ac837e4597 to your computer and use it in GitHub Desktop.
Save devshorts/0b7cc8268adee6b1468d94ac837e4597 to your computer and use it in GitHub Desktop.
golang zip
package packaging
import (
"archive/zip"
"io"
)
type PackageContents struct {
Data io.Reader
FileName string
}
// Writes a zip file to the writer with the package contents
func Zip(contents []PackageContents, output io.Writer) error {
zipWriter := zip.NewWriter(output)
for _, file := range contents {
zipEntry, err := zipWriter.CreateHeader(&zip.FileHeader{
Name: file.FileName,
})
if err != nil {
return err
}
_, err = io.Copy(zipEntry, file.Data)
if err != nil {
return err
}
}
err := zipWriter.Close()
if err != nil {
return err
}
return nil
}
// Given a zip file reader stream gets a writer for each file
// and allows you to dump the contents of the zip file to the writer
// zips require random access so we need to know the content size
// and have a reader that supports random reads
func Unzip(zipFile io.ReaderAt, contentsSize int, writerProvider func(fileName string) io.Writer) error {
zipReader, err := zip.NewReader(zipFile, int64(contentsSize))
if err != nil {
return err
}
for _, file := range zipReader.File {
fileWriter := writerProvider(file.Name)
fileReaderCloser, err := file.Open()
if err != nil {
return err
}
_, err = io.Copy(fileWriter, fileReaderCloser)
if err != nil {
return err
}
}
return nil
}
package packaging
import (
"bytes"
"io"
"io/ioutil"
"testing"
"github.com/stretchr/testify/assert"
)
func TestZipUnzip(t *testing.T) {
testFileData := "data"
buffer := bytes.NewBuffer([]byte{})
testFile := PackageContents{
FileName: "test.txt",
Data: bytes.NewReader([]byte(testFileData)),
}
_ = Zip([]PackageContents{testFile}, buffer)
zippedBytes, _ := ioutil.ReadAll(buffer)
assert.True(t, len(zippedBytes) > 0)
resultBuffer := bytes.NewBuffer([]byte{})
_ = Unzip(bytes.NewReader(zippedBytes), len(zippedBytes), func(fileName string) io.Writer {
// verify the filename is properly called back
t.Helper()
assert.Equal(t, testFile.FileName, fileName)
return resultBuffer
})
unzippedTestFileData, _ := ioutil.ReadAll(resultBuffer)
// assert we were able to unzip the data and that the resulting file is equal to the
// original
assert.Equal(t, []byte(testFileData), unzippedTestFileData)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment