package
main
import
(
"archive/zip"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
)
func
main() {
files, err := Unzip(
"compression-test.zip"
,
"uncompressed files"
)
if
err != nil {
log.Fatal(err)
}
fmt.Println(
"Unzipped the following files:\n"
+ strings.Join(files,
"\n"
))
}
func
Unzip(src
string
, destination
string
) ([]
string
, error) {
var
filenames []
string
r, err := zip.OpenReader(src)
if
err != nil {
return
filenames, err
}
defer
r.Close()
for
_, f :=
range
r.File {
fpath := filepath.Join(destination, f.Name)
if
!strings.HasPrefix(fpath, filepath.Clean(destination)+
string
(os.PathSeparator)){
return
filenames, fmt.Errorf(
"%s is an illegal filepath"
, fpath)
}
filenames = append(filenames, fpath)
if
f.FileInfo().IsDir() {
os.MkdirAll(fpath, os.ModePerm)
continue
}
if
err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return
filenames, err
}
outFile, err := os.OpenFile(fpath,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
f.Mode())
if
err != nil {
return
filenames, err
}
rc, err := f.Open()
if
err != nil {
return
filenames, err
}
_, err = io.Copy(outFile, rc)
outFile.Close()
rc.Close()
if
err != nil {
return
filenames, err
}
}
return
filenames, nil
}