dtpxi88884 2019-08-15 02:37
浏览 507

如何在Go中将文件压缩为不带目录文件夹的.zip

There're examples about compressing a file to .zip in Go. However, the file they generate include the directory folder. When I decompress the .zip file, there will be a new folder.

So, how can I compress a file to .zip without getting the directory folder included?

An example:

https://golangcode.com/create-zip-files-in-go/

package main

import (
    "archive/zip"
    "fmt"
    "io"
    "os"
)

func main() {

    // List of Files to Zip
    files := []string{"example.csv", "data.csv"}
    output := "done.zip"

    if err := ZipFiles(output, files); err != nil {
        panic(err)
    }
    fmt.Println("Zipped File:", output)
}

// ZipFiles compresses one or many files into a single zip archive file.
// Param 1: filename is the output zip file's name.
// Param 2: files is a list of files to add to the zip.
func ZipFiles(filename string, files []string) error {

    newZipFile, err := os.Create(filename)
    if err != nil {
        return err
    }
    defer newZipFile.Close()

    zipWriter := zip.NewWriter(newZipFile)
    defer zipWriter.Close()

    // Add files to zip
    for _, file := range files {
        if err = AddFileToZip(zipWriter, file); err != nil {
            return err
        }
    }
    return nil
}

func AddFileToZip(zipWriter *zip.Writer, filename string) error {

    fileToZip, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer fileToZip.Close()

    // Get the file information
    info, err := fileToZip.Stat()
    if err != nil {
        return err
    }

    header, err := zip.FileInfoHeader(info)
    if err != nil {
        return err
    }

    // Using FileInfoHeader() above only uses the basename of the file. If we want
    // to preserve the folder structure we can overwrite this with the full path.
    header.Name = filename

    // Change to deflate to gain better compression
    // see http://golang.org/pkg/archive/zip/#pkg-constants
    header.Method = zip.Deflate

    writer, err := zipWriter.CreateHeader(header)
    if err != nil {
        return err
    }
    _, err = io.Copy(writer, fileToZip)
    return err
}
  • 写回答

1条回答 默认 最新

  • doqrjrc95405 2019-08-15 06:30
    关注

    Just use a base name of the file in the zip header.

    header.Name = filepath.Base(filename)
                  ^^^^^^^^^^^^^^
    

    Here is a version that does the same thing

    package main
    
    import (
        "archive/zip"
        "io"
        "log"
        "os"
        "path/filepath"
    )
    
    func createFlatZip(w io.Writer, files ...string) error {
        z := zip.NewWriter(w)
        for _, file := range files {
            src, err := os.Open(file)
            if err != nil {
                return err
            }
            info, err := src.Stat()
            if err != nil {
                return err
            }
            hdr, err := zip.FileInfoHeader(info)
            if err != nil {
                return err
            }
            hdr.Name = filepath.Base(file) // Write only the base name in the header
            dst, err := z.CreateHeader(hdr)
            if err != nil {
                return err
            }
            _, err = io.Copy(dst, src)
            if err != nil {
                return err
            }
            src.Close()
        }
        return z.Close()
    }
    
    func main() {
        if len(os.Args) < 3 {
            log.Fatalf("archive name and at least one file are required")
        }
        a, err := os.Create(os.Args[1])
        if err != nil {
            log.Fatal(err)
        }
        defer a.Close()
    
        err = createFlatZip(a, os.Args[2:]...)
        if err != nil {
            log.Fatal(err)
        }
    }
    

    Results:

    ~/src/gozip
    ➜ go build
    
    ~/src/gozip
    ➜ mkdir test && echo 1 > test/1.txt # create a test file in a subfolder
    
    ~/src/gozip
    ➜ ./gozip 1.zip test/1.txt
    
    ~/src/gozip
    ➜ unzip -l 1.zip
    Archive:  1.zip
      Length      Date    Time    Name
    ---------  ---------- -----   ----
            2  08-15-2019 01:29   1.txt
    ---------                     -------
            2                     1 file
    
    评论

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作