- 
      
 - 
        
Save iamralch/424e6784facc0ba907ae to your computer and use it in GitHub Desktop.  
| import ( | |
| "archive/zip" | |
| "io" | |
| "os" | |
| "path/filepath" | |
| "strings" | |
| ) | |
| func zipit(source, target string) error { | |
| zipfile, err := os.Create(target) | |
| if err != nil { | |
| return err | |
| } | |
| defer zipfile.Close() | |
| archive := zip.NewWriter(zipfile) | |
| defer archive.Close() | |
| info, err := os.Stat(source) | |
| if err != nil { | |
| return nil | |
| } | |
| var baseDir string | |
| if info.IsDir() { | |
| baseDir = filepath.Base(source) | |
| } | |
| filepath.Walk(source, func(path string, info os.FileInfo, err error) error { | |
| if err != nil { | |
| return err | |
| } | |
| header, err := zip.FileInfoHeader(info) | |
| if err != nil { | |
| return err | |
| } | |
| if baseDir != "" { | |
| header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source)) | |
| } | |
| if info.IsDir() { | |
| header.Name += "/" | |
| } else { | |
| header.Method = zip.Deflate | |
| } | |
| writer, err := archive.CreateHeader(header) | |
| if err != nil { | |
| return err | |
| } | |
| if info.IsDir() { | |
| return nil | |
| } | |
| file, err := os.Open(path) | |
| if err != nil { | |
| return err | |
| } | |
| defer file.Close() | |
| _, err = io.Copy(writer, file) | |
| return err | |
| }) | |
| return err | |
| } | 
| import ( | |
| "archive/zip" | |
| "io" | |
| "os" | |
| "path/filepath" | |
| "strings" | |
| ) | |
| func unzip(archive, target string) error { | |
| reader, err := zip.OpenReader(archive) | |
| if err != nil { | |
| return err | |
| } | |
| if err := os.MkdirAll(target, 0755); err != nil { | |
| return err | |
| } | |
| for _, file := range reader.File { | |
| path := filepath.Join(target, file.Name) | |
| if file.FileInfo().IsDir() { | |
| os.MkdirAll(path, file.Mode()) | |
| continue | |
| } | |
| fileReader, err := file.Open() | |
| if err != nil { | |
| return err | |
| } | |
| defer fileReader.Close() | |
| targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode()) | |
| if err != nil { | |
| return err | |
| } | |
| defer targetFile.Close() | |
| if _, err := io.Copy(targetFile, fileReader); err != nil { | |
| return err | |
| } | |
| } | |
| return nil | |
| } | 
The extract function will generate too many open file issue as the defer is only called once the function return, here an altered version:
func Unzip(archive, target string) error {
    reader, err := zip.OpenReader(archive)
    if err != nil {
        return err
    }
    if err := os.MkdirAll(target, 0755); err != nil {
        return err
    }
    for _, file := range reader.File {
        path := filepath.Join(target, file.Name)
        if file.FileInfo().IsDir() {
            os.MkdirAll(path, file.Mode())
            continue
        }
        fileReader, err := file.Open()
        if err != nil {
            if fileReader != nil {
                fileReader.Close()
            }
            return err
        }
        targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
        if err != nil {
            fileReader.Close()
            if targetFile != nil {
                targetFile.Close()
            }
            return err
        }
        if _, err := io.Copy(targetFile, fileReader); err != nil {
            fileReader.Close()
            targetFile.Close()
            return err
        }
        fileReader.Close()
        targetFile.Close()
    }
    return nil
}The zipit function throws an error if the .zip file does not already exist. How do i remedy this?
	// Check file
	if _, err := os.Stat(archive); os.IsNotExist(err) {
		return err
	}
    License?
If have a large files in multiple directory, the filepath.Walk would take a long time to process. Any possible to use goroutine to improve performance?
hi all, if I have some sub directories, in the code previous, it just make directory of sub directories, how can i restore those files in sub directories?
if r.File[f].FileInfo().IsDir() {
if err := os.MkdirAll(dstpath, os.ModePerm); err != nil {
return nil, err
}
}
in this piece of code, how could i copy those files which are in this directory?
You have to walk through the directories until you reach a regular file.
@Svett, thanks for the very useful code. I have a question on line 21 in compress.go. Is there any reason to return
nilinstead oferrin this case?