How to Unzip a Zip File In Go - Backup Files Software From Scratch Written in Golang Tutorial #10

Опубликовано: 30 Сентябрь 2024
на канале: Maharlikans Code
582
6

In this tutorial series #10, we will learn how to decompress or unzip the .zip file extension using Golang programming language with step by step guide.

#MaharlikansCode
#UNZIPInGolang
#Golang
#UnzipAZipFileInGo
#LifeAsSoftwareDeveloper
#Maharlikans
#FilipinoSoftwareDeveloper

If you go with extra mile for buying me a cup of coffee, I appreciate it guys: https://ko-fi.com/maharlikanscode

Source Codes:
cmd/dcfile.go:
package cmd

import (
"path/filepath"
"time"

"github.com/fatih/color"
"github.com/itrepablik/itrlog"
"github.com/itrepablik/kopy"

"github.com/spf13/cobra"
)

// dcfileCmd represents the dcfile command
var dcfileCmd = &cobra.Command{
Use: "dcfile",
Short: "Decompress any single zip file",
Long: `dcfile command decompress any single .zip compression file format.
Only the .zip file formats will be decompressed by this command.

Example of a valid directory path in Windows:
"C:\source_folder\filename.zip"

Or using the network directories, example:
"\\hostname_or_ip\source_folder\filename.zip"`,
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
// To make directory path separator a universal, in Linux "/" and in Windows "\" to auto change
// depends on the user's OS using the filepath.FromSlash organic Go's library.
src := filepath.FromSlash(args[0])

msg := `Start decompressing:`
color.Blue(msg + " " + src)
itrlog.Errorw(msg, "src", src, "log_time", time.Now().Format(logDTFormat))

if err := kopy.Unzip(src, dcfileLog); err != nil {
color.Red(err.Error())
itrlog.Errorw("error", "err", err, "log_time", time.Now().Format(logDTFormat))
return
}

msg = `Done decompressing:`
color.Green(msg + " " + src)
itrlog.Errorw(msg, "src", src, "log_time", time.Now().Format(logDTFormat))
},
}

func init() {
rootCmd.AddCommand(dcfileCmd)
}

kopy.Unzip:
// Unzip will decompress a zip archive, moving all files and folders
// within the zip file (parameter 1) to an output directory (parameter 2).
func Unzip(src string, isLogCopiedFile bool) error {
// Read the compressed file's original source folder or directory.
zipReader, err := zip.OpenReader(src)

fnExtract := ""
if b := strings.Contains(src, ComSingleFileFormat); b {
fnExtract = strings.Replace(src, ComSingleFileFormat, "", -1)
}

os.MkdirAll(fnExtract, os.ModePerm) // Create a new dst dir first
for _, file := range zipReader.Reader.File {
zippedFile, err := file.Open()
if err != nil {
return err
}
defer zippedFile.Close()

folderPath := filepath.FromSlash(file.Name) //full file path
extractFileTo := ""

// Replace the original folder root directory of the compressed folder to a new dst location.
if b := strings.Contains(folderPath, filepath.Dir(folderPath)); b {
extractFileTo = strings.Replace(folderPath, filepath.Dir(folderPath), fnExtract, -1)
}
extractedFilePath := filepath.Join(extractFileTo, file.Name)

if file.FileInfo().IsDir() {
if err := os.MkdirAll(filepath.FromSlash(extractedFilePath), os.ModePerm); err != nil {
color.Red(err.Error())
itrlog.Fatalf("error", "err", err.Error(), "log_time", time.Now().Format(logDateTimeFormat))
}
} else {
folderPath := filepath.FromSlash(file.Name) //full file path
extractFileTo := ""

// Replace the original folder root directory of the compressed folder to a new dst location.
if b := strings.Contains(folderPath, filepath.Dir(folderPath)); b {
extractFileTo = strings.Replace(folderPath, filepath.Dir(folderPath), fnExtract, -1)
}
outputFile, err := os.OpenFile(extractFileTo, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())

if err != nil {
return err
}
defer outputFile.Close()

if _, err = io.Copy(outputFile, zippedFile); err != nil {
return err
}

// Only log when it's true
if isLogCopiedFile {
color.Magenta("extracting to: " + extractFileTo)
itrlog.Infow("extracting to: ", "dst", extractFileTo, "log_time", time.Now().Format(logDateTimeFormat))
}
}
}
return err
}

config.yaml:
dcfile:
log: true # true or false, make it true to log each copied file

root.go:
// ConfigDCFile is the collection of the dcfile config values
type ConfigDCFile struct {
Log bool
}

var conDelDir []ConfigDelDir
var dcfileLog bool = false

func LoadViperCofig() {
...
// Get the config values for the 'default.command_properties.deldir' keys from the config.yaml file
err = viper.UnmarshalKey("default.command_properties.deldir", &conDelDir)
if err != nil {
itrlog.Error(err)
}
for _, a := range conDelDir {
deldirIgnore = a.Ignore
deldirLog = a.Log
}
}