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:
- 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 thezipSource()
perform. - 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 thesupply
path utilizing thefilepath.Stroll()
perform. - 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 tozip.Deflate
. - 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 fromfs.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 thesupply
path listing to the desired filepath
utilizingfilepath.Dir()
andfilepath.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.
- 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.