easy way to unzip file with golang

后端 未结 8 763
情话喂你
情话喂你 2021-02-01 03:45

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 !         


        
相关标签:
8条回答
  • 2021-02-01 04:22
    package main
    
    import (
        "os"
        "io"
        "io/ioutil"
        "fmt"
        "strings"
        "archive/zip"
        "path/filepath"
    )
    
    func main() {
        if err := foo("test.zip"); err != nil {
            fmt.Println(err)
        }
    }
    
    func foo(yourZipFile string) error {
        tmpDir, err := ioutil.TempDir("/tmp", "yourPrefix-")
        if err != nil {
            return err
        }
        defer os.RemoveAll(tmpDir)
        if filenames, err := Unzip(yourZipFile, tmpDir); err != nil {
            return err
        } else {
            for f := range filenames {
                fmt.Println(filenames[f])
            }
        }
        return nil
    }
    
    
    func Unzip(src string, dst string) ([]string, error) {
        var filenames []string
        r, err := zip.OpenReader(src)
        if err != nil {
            return nil, err
        }
        defer r.Close()
        for f := range r.File {
            dstpath := filepath.Join(dst, r.File[f].Name)
            if !strings.HasPrefix(dstpath, filepath.Clean(dst) + string(os.PathSeparator)) {
                return nil, fmt.Errorf("%s: illegal file path", src)
            }
            if r.File[f].FileInfo().IsDir() {
                if err := os.MkdirAll(dstpath, os.ModePerm); err != nil {
                    return nil, err
                }
            } else {
                if rc, err := r.File[f].Open(); err != nil {
                    return nil, err
                } else {
                    defer rc.Close()
                    if of, err := os.OpenFile(dstpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, r.File[f].Mode()); err != nil {
                        return nil, err
                    } else {
                        defer of.Close()
                        if _, err = io.Copy(of, rc); err != nil {
                            return nil, err
                        } else {
                            of.Close()
                            rc.Close()
                            filenames = append(filenames, dstpath)
                        }
                    }
                }
            }
        }
        if len(filenames) == 0 {
            return nil, fmt.Errorf("zip file is empty")
        }
        return filenames, nil
    }
    
    0 讨论(0)
  • 2021-02-01 04:27

    Every single answer on this page is wrong, as they all assume that the Zip archive will emit directory entries. Zip archives are not required to emit directory entries, and so given an archive such as that, a naive program will crash upon encountering the first non-root file, as no directories will ever be created, and the file creation will fail as the directory has not been created yet. Here is a different approach:

    package main
    
    import (
       "archive/zip"
       "os"
       "path"
    )
    
    func Unzip(source string) error {
       zip_o, e := zip.OpenReader(source)
       if e != nil {
          return e
       }
       for _, file_o := range zip_o.File {
          if file_o.Mode().IsDir() {
             continue
          }
          dir_s := path.Dir(file_o.Name)
          os.MkdirAll(dir_s, os.ModeDir)
          open_o, e := file_o.Open()
          if e != nil {
             return e
          }
          create_o, e := os.Create(file_o.Name)
          if e != nil {
             return e
          }
          create_o.ReadFrom(open_o)
       }
       return nil
    }
    

    Example use:

    package main
    import "log"
    
    func main() {
       e := Unzip("Microsoft.VisualCpp.Tools.HostX64.TargetX64.vsix")
       if e != nil {
          log.Fatal(e)
       }
    }
    
    0 讨论(0)
提交回复
热议问题