Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

easy way to unzip file with golang

Tags:

zip

go

unzip

is there a easy way to unzip file with golang ?

right now my code is:

func Unzip(src, dest string) error {     r, err := zip.OpenReader(src)     if err != nil {         return err     }     defer r.Close()      for _, f := range r.File {         rc, err := f.Open()         if err != nil {             return err         }         defer rc.Close()          path := filepath.Join(dest, f.Name)         if f.FileInfo().IsDir() {             os.MkdirAll(path, f.Mode())         } else {             f, err := os.OpenFile(                 path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())             if err != nil {                 return err             }             defer f.Close()              _, err = io.Copy(f, rc)             if err != nil {                 return err             }         }     }      return nil } 
like image 218
Akshay Deep Giri Avatar asked Dec 03 '13 17:12

Akshay Deep Giri


People also ask

How do I unzip a ZIP file in Terminal?

To extract the files from a ZIP file, use the unzip command, and provide the name of the ZIP file. Note that you do need to provide the “. zip” extension. As the files are extracted they are listed to the terminal window.


2 Answers

Slight rework of the OP's solution to create the containing directory dest if it doesn't exist, and to wrap the file extraction/writing in a closure to eliminate stacking of defer .Close() calls per @Nick Craig-Wood's comment:

func Unzip(src, dest string) error {     r, err := zip.OpenReader(src)     if err != nil {         return err     }     defer func() {         if err := r.Close(); err != nil {             panic(err)         }     }()      os.MkdirAll(dest, 0755)      // Closure to address file descriptors issue with all the deferred .Close() methods     extractAndWriteFile := func(f *zip.File) error {         rc, err := f.Open()         if err != nil {             return err         }         defer func() {             if err := rc.Close(); err != nil {                 panic(err)             }         }()          path := filepath.Join(dest, f.Name)          // Check for ZipSlip (Directory traversal)         if !strings.HasPrefix(path, filepath.Clean(dest) + string(os.PathSeparator)) {             return fmt.Errorf("illegal file path: %s", path)         }          if f.FileInfo().IsDir() {             os.MkdirAll(path, f.Mode())         } else {             os.MkdirAll(filepath.Dir(path), f.Mode())             f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())             if err != nil {                 return err             }             defer func() {                 if err := f.Close(); err != nil {                     panic(err)                 }             }()              _, err = io.Copy(f, rc)             if err != nil {                 return err             }         }         return nil     }      for _, f := range r.File {         err := extractAndWriteFile(f)         if err != nil {             return err         }     }      return nil } 

Note: Updated to include Close() error handling as well (if we're looking for best practices, may as well follow ALL of them).

like image 199
Astockwell Avatar answered Sep 28 '22 15:09

Astockwell


I'm using archive/zip package to read .zip files and copy to the local disk. Below is the source code to unzip .zip files for my own needs.

import (     "archive/zip"     "io"     "log"     "os"     "path/filepath"     "strings" )  func unzip(src, dest string) error {     r, err := zip.OpenReader(src)     if err != nil {         return err     }     defer r.Close()      for _, f := range r.File {         rc, err := f.Open()         if err != nil {             return err         }         defer rc.Close()          fpath := filepath.Join(dest, f.Name)         if f.FileInfo().IsDir() {             os.MkdirAll(fpath, f.Mode())         } else {             var fdir string             if lastIndex := strings.LastIndex(fpath,string(os.PathSeparator)); lastIndex > -1 {                 fdir = fpath[:lastIndex]             }              err = os.MkdirAll(fdir, f.Mode())             if err != nil {                 log.Fatal(err)                 return err             }             f, err := os.OpenFile(                 fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())             if err != nil {                 return err             }             defer f.Close()              _, err = io.Copy(f, rc)             if err != nil {                 return err             }         }     }     return nil } 
like image 38
swtdrgn Avatar answered Sep 28 '22 15:09

swtdrgn