filezip.go 8.23 KiB
Newer Older
package filemdl

import (
	"archive/zip"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"

	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/errormdl"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl"
Shridhar I. Patil's avatar
Shridhar I. Patil committed

	// "github.com/DataDog/zstd"
	"github.com/klauspost/compress/zstd"
Shridhar I. Patil's avatar
Shridhar I. Patil committed
var encoder, _ = zstd.NewWriter(nil)
var decoder, _ = zstd.NewReader(nil)

//Zip - Zip
func Zip(source, target string) error {
	source = filepath.Clean(source)
	target = filepath.Clean(target)

	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 err
	}

	var baseDir string
	if info.IsDir() {
		baseDir = filepath.Base(source)
	}

	filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
		if errormdl.CheckErr(err) != nil {
			return errormdl.CheckErr(err)
		}

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

		if baseDir != "" {
			header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
			// Replace all occurances of \\ with /. This is necessary to properly unzip the zip file created on windows system on ubuntu system
			header.Name = strings.Replace(header.Name, "\\", "/", -1)
		}

		if info.IsDir() {
			header.Name += "/"
		} else {
			header.Method = zip.Deflate
		}

		writer, err := archive.CreateHeader(header)
		if errormdl.CheckErr(err) != nil {
			return errormdl.CheckErr(err)
		}

		if info.IsDir() {
			return nil
		}

		file, err := os.Open(path)
		if errormdl.CheckErr(err) != nil {
			return errormdl.CheckErr(err)
		}
		_, err = io.Copy(writer, file)
		if errormdl.CheckErr(err) != nil {
		}

		file.Close()
		return errormdl.CheckErr(err)
	})

	return errormdl.CheckErr(err)
}

//ZipWithoutBaseDirectory Zip Without Base Directory
func ZipWithoutBaseDirectory(source, target string) error {
	source = filepath.Clean(source)
	target = filepath.Clean(target)

	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 err
	}

	var baseDir string
	if info.IsDir() {
		baseDir = filepath.Base(source)
	}

	filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
		if errormdl.CheckErr(err) != nil {
			return errormdl.CheckErr(err)
		}

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

		if baseDir != "" {
			header.Name = strings.TrimPrefix(path, source)
			// Replace all occurances of \\ with /. This is necessary to properly unzip the zip file created on windows system on ubuntu system
			header.Name = strings.Replace(header.Name, "\\", "/", -1)
		}

		if info.IsDir() {
			header.Name += "/"
		} else {
			header.Method = zip.Deflate
		}

		writer, err := archive.CreateHeader(header)
		if errormdl.CheckErr(err) != nil {
			return errormdl.CheckErr(err)
		}

		if info.IsDir() {
			return nil
		}

		file, err := os.Open(path)
		if errormdl.CheckErr(err) != nil {
			return errormdl.CheckErr(err)
		}
		_, err = io.Copy(writer, file)
		if errormdl.CheckErr(err) != nil {
		}

		file.Close()
		return errormdl.CheckErr(err)
	})

	return errormdl.CheckErr(err)
}

//ZipWithSkipFileList This method will skip the file added in skiplist from zip
func ZipWithSkipFileList(source, target string, skipFileList []string) error {

	source = filepath.Clean(source)
	target = filepath.Clean(target)
	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 err
	}
	var baseDir string
	if info.IsDir() {
		baseDir = filepath.Base(source)
	}
	filepath.Walk(source, func(path string, info os.FileInfo, err error) error {

		if !checkPathInSkipList(info.Name(), skipFileList) {
			header, err := zip.FileInfoHeader(info)
			if errormdl.CheckErr(err) != nil {
				return errormdl.CheckErr(err)
			}

			if baseDir != "" {
				header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
				// Replace all occurances of \\ with /. This is necessary to properly unzip the zip file created on windows system on ubuntu system
				header.Name = strings.Replace(header.Name, "\\", "/", -1)
			}

			if info.IsDir() {
				header.Name += "/"
			} else {
				header.Method = zip.Deflate
			}

			writer, err := archive.CreateHeader(header)
			if errormdl.CheckErr(err) != nil {
				return errormdl.CheckErr(err)
			}

			if info.IsDir() {
				return nil
			}

			file, err := os.Open(path)
			if errormdl.CheckErr(err) != nil {
				return errormdl.CheckErr(err)
			}

			_, err = io.Copy(writer, file)
			if err != nil {
			}

			file.Close()
			return nil
		}

		return nil
	})
	return errormdl.CheckErr(err)
}

func checkPathInSkipList(path string, skipList []string) bool {
	for _, prefix := range skipList {
		if strings.HasPrefix(path, prefix) {
			return true
		}
		if strings.HasSuffix(path, prefix) {
			return true
		}
	}
	return false
}

//Unzip Unzip
func Unzip(archive, target string) error {
	reader, err := zip.OpenReader(archive)
	if err != nil {
		loggermdl.LogError(err)
		return err
	}

	mkcDirError := os.MkdirAll(target, 0755)
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
	if errormdl.CheckErr(mkcDirError) != nil {
		loggermdl.LogError(errormdl.CheckErr(mkcDirError))
		return errormdl.CheckErr(mkcDirError)
	}

	for _, file := range reader.File {
		filePath := filepath.Join(target, file.Name)
		parentPath := path.Dir(CleanPath(filePath))

		if !FileAvailabilityCheck(parentPath) {
			CreateDirectoryRecursive(parentPath)
		}

		if file.FileInfo().IsDir() {
			os.MkdirAll(filePath, file.Mode())
			continue
		}

		fileReader, openError := file.Open()
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
		if errormdl.CheckErr(openError) != nil {
			loggermdl.LogError(errormdl.CheckErr(openError))
			return errormdl.CheckErr(openError)
		}

		targetFile, targetOpenError := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
		if errormdl.CheckErr(targetOpenError) != nil {
			loggermdl.LogError(errormdl.CheckErr(targetOpenError))
			return errormdl.CheckErr(targetOpenError)
		}

		_, copyError := io.Copy(targetFile, fileReader)
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
		if errormdl.CheckErr(copyError) != nil {
			loggermdl.LogError(errormdl.CheckErr(copyError))
			return errormdl.CheckErr(copyError)
		}
		targetCloseError := targetFile.Close()
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
		if errormdl.CheckErr(targetCloseError) != nil {
			loggermdl.LogError(errormdl.CheckErr(targetCloseError))
			return errormdl.CheckErr(targetCloseError)
		}

		fileCloseError := fileReader.Close()
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
		if errormdl.CheckErr(fileCloseError) != nil {
			loggermdl.LogError(errormdl.CheckErr(fileCloseError))
			return errormdl.CheckErr(fileCloseError)
		}
	}
	closeError := reader.Close()
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
	if errormdl.CheckErr(closeError) != nil {
		loggermdl.LogError(errormdl.CheckErr(closeError))
		return errormdl.CheckErr(closeError)
Shridhar I. Patil's avatar
Shridhar I. Patil committed
//ZipBytes - zip byte array
Roshan Patil's avatar
Roshan Patil committed
func ZipBytes(inputData []byte) ([]byte, error) {
Shridhar I. Patil's avatar
Shridhar I. Patil committed
	// compressedData, err := zstd.CompressLevel(nil, inputData, 9)
	compressedData := encoder.EncodeAll(inputData, make([]byte, 0, len(inputData)))
	return compressedData, nil
}

// ZipSingleFile - Zip single file
func ZipSingleFile(sourceFilePath, destFilePath string) error {
	inputData, err := ioutil.ReadFile(sourceFilePath)
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
	if err != nil {
		return err
Roshan Patil's avatar
Roshan Patil committed
	compressedData, err := ZipBytes(inputData)
	if errormdl.CheckErr(err) != nil {
		return errormdl.CheckErr(err)
	}
	err = ioutil.WriteFile(destFilePath, compressedData, 0644)
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
	if err != nil {
		return err
Shridhar I. Patil's avatar
Shridhar I. Patil committed
//UnZipBytes bytes - Decompress
Roshan Patil's avatar
Roshan Patil committed
func UnZipBytes(compressedData []byte) ([]byte, error) {
Shridhar I. Patil's avatar
Shridhar I. Patil committed
	// decompressedData, err := zstd.Decompress(nil, compressedData)
	decompressedData, err := decoder.DecodeAll(compressedData, nil)
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
	return decompressedData, errormdl.CheckErr(err)
}

// UnZipSingleFile - UnZip Single File
func UnZipSingleFile(sourceFilePath, destFilePath string) error {
	inputData, err := ioutil.ReadFile(sourceFilePath)
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
	if err != nil {
		return err
Roshan Patil's avatar
Roshan Patil committed
	uncompressedData, err := UnZipBytes(inputData)
	if errormdl.CheckErr(err) != nil {
		return errormdl.CheckErr(err)
	}
	err = ioutil.WriteFile(destFilePath, uncompressedData, 0644)
Mahendra Vishwakarma's avatar
Mahendra Vishwakarma committed
	if err != nil {
		return err