Saturday, May 4, 2024
HomeGolangZip a file in Go (Golang)

Zip a file in Go (Golang)



To zip a file or a listing in Go utilizing the usual library, use zip.Author sort from the archive/zip bundle. Making a compressed archive utilizing this methodology includes going via all of the recordsdata you need to embrace, producing a native file header for every one, and writing its contents to the ensuing ZIP file.

Examine additionally our instance on the way to unzip a file in Go

bundle essential

import (
    "archive/zip"
    "io"
    "log"
    "os"
    "path/filepath"
)

func zipSource(supply, goal string) error {
    // 1. Create a ZIP file and zip.Author
    f, err := os.Create(goal)
    if err != nil {
        return err
    }
    defer f.Shut()

    author := zip.NewWriter(f)
    defer author.Shut()

    // 2. Undergo all of the recordsdata of the supply
    return filepath.Stroll(supply, func(path string, data os.FileInfo, err error) error {
        if err != nil {
            return err
        }

        // 3. Create an area file header
        header, err := zip.FileInfoHeader(data)
        if err != nil {
            return err
        }

        // set compression
        header.Technique = zip.Deflate

        // 4. Set relative path of a file because the header title
        header.Title, err = filepath.Rel(filepath.Dir(supply), path)
        if err != nil {
            return err
        }
        if data.IsDir() {
            header.Title += "/"
        }

        // 5. Create author for the file header and save content material of the file
        headerWriter, err := author.CreateHeader(header)
        if err != nil {
            return err
        }

        if data.IsDir() {
            return nil
        }

        f, err := os.Open(path)
        if err != nil {
            return err
        }
        defer f.Shut()

        _, err = io.Copy(headerWriter, f)
        return err
    })
}

func essential() {
    if err := zipSource("testFolder", "testFolder.zip"); err != nil {
        log.Deadly(err)
    }
    if err := zipSource("testFolder/1/1.1/1.1.txt", "1.1.zip"); err != nil {
        log.Deadly(err)
    }
}

Within the instance above, we use a pattern listing testFolder:

testFolder
├── 1
│   └── 1.1
│       └── 1.1.txt
├── 2
└── take a look at.txt

The zipSource(supply, goal string) perform does the next:

  1. Create a ZIP file and zip.Author
    // 1. Create a ZIP file and zip.Author
    f, err := os.Create(goal)
    if err != nil {
        return err
    }
    defer f.Shut()
    
    author := zip.NewWriter(f)
    defer author.Shut()
    

    In step one, we have to create a ZIP file and initialize zip.Author that writes the compressed knowledge to the file. Discover that we defer closing the file and the author to the top of the zipSource() perform.

  2. Undergo all of the recordsdata of the supply
    // 2. Undergo all of the recordsdata of the supply
    return filepath.Stroll(supply, func(path string, data os.FileInfo, err error) error {
    ...
    })
    

    We would like the zipSource() perform to work on each a single file and a folder, so we have to stroll via every file of the supply path utilizing the filepath.Stroll() perform.

  3. Create an area file header
    // 3. Create an area file header
    header, err := zip.FileInfoHeader(data)
    if err != nil {
        return err
    }
    
    // set compression
    header.Technique = zip.Deflate
    

    For every file within the archive, we have to create a native file header utilizing the FileInfoHeader() perform. The generated header doesn’t have the compression methodology set, so we explicitly set it to zip.Deflate.

  4. Set the relative path of a file because the header title
    // 4. Set relative path of a file because the header title
    header.Title, err = filepath.Rel(filepath.Dir(supply), path)
    if err != nil {
        return err
    }
    if data.IsDir() {
        header.Title += "/"
    }
    

    Within the earlier step, we created a file header utilizing FileInfoHeader(fi fs.FileInfo) perform with the title from fs.FileInfo argument. Nevertheless, that is only a base title, so we have to modify it to protect the listing construction within the generated ZIP. We do that by calculating the relative path from the supply path listing to the desired file path utilizing filepath.Dir() and filepath.Rel() capabilities. For instance, compressing the /a/b/c listing with /a/b/c/d/take a look at.txt file provides us:

    filepath.Rel(filepath.Dir("/a/b/c"), "/a/b/c/d/take a look at.txt")
    

    which is equal to:

    filepath.Rel("/a/b/", "/a/b/c/d/take a look at.txt")
    

    Because of this, we get the relative path:

    Additionally, if the file is a listing, it needs to be marked with a trailing slash.

  5. Create author for the file header and save content material of the file
    // 5. Create a author for the file header and save the content material of the file
    headerWriter, err := author.CreateHeader(header)
    if err != nil {
        return err
    }
    
    if data.IsDir() {
        return nil
    }
    
    f, err := os.Open(path)
    if err != nil {
        return err
    }
    defer f.Shut()
    
    _, err = io.Copy(headerWriter, f)
    return err
    

    The final step is to create a author for the desired file knowledge primarily based on the header. The information is transferred to the ZIP file utilizing the io.Copy() perform. Recordsdata which might be directories shouldn’t be copied to keep away from an error.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments