Use case is: I want to zip a folder which could contain n number of files with difference sizes. I want to add limit like if the zip size > x (MB|GB) then do not create the zip and throw error. I tried to get the size of zip file after the zip is created after iterating the folder but not able to do so. Request help here. I am using io.writer to create zip file instead buffer. Sample code is
Note: I am able to calculate the size when using "buf := new(bytes.Buffer)" but I want to calculate using io.writer as seen below
filepath - Path to the folder downloadLimit - the limit I want to set for downloaded zip file. Like zip file size should not be more then 100 MB
func GetZipFileSize(filepath string, downloadLimit int, w io.Writer) error {
zipWriter := zip.NewWriter(w)
// List files
var files []FileAndPath
var err error
// We have function to fetch files in variable "files" which is used below
// ZIP files
for _, file := range files {
// Determine filename in ZIP
zipFilename := file.Path
filename := fp.Join(SOME_PATH, file.Path)
// Create ZIP entry
fileToZip, err := os.Open(filename)
if err != nil {
return SOME_ERROR
}
info, err := fileToZip.Stat()
if err != nil {
return err
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Name = zipFilename
header.Method = zip.Deflate
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
// Set content for ZIP entry
if _, err = io.Copy(writer, fileToZip); err != nil {
return err
}
if err = fileToZip.Close(); err != nil {
// Nothing
}
}
// Wrap-up
if err := zipWriter.Close(); err != nil {
return err
}
return nil
}
Above function create zip file, but I want it to stop creation as soon the limit is reached and exit OR at least get the size of the zip file created
The standard API does not provide an io.Writer
implementaion to do that, afaik. It exists a LimitReader
but it is of little use for your case and would led us to write rather complex code.
Instead, you can write your own io.Writer
wrapper implementation to ensure that if the total amount of bytes written onto it exceeds some length, or is about to, return an error.
package main
import (
"errors"
"fmt"
"io"
"os"
"strings"
)
func main() {
bigBuf := strings.NewReader(strings.Repeat("borng string", 10000))
dst := &LimitWriter{Writer: os.Stdout, N: 20}
n, err := io.Copy(dst, bigBuf)
fmt.Println("n=", n)
fmt.Println("err=", err)
}
var ErrWriteOverflow = errors.New("write overflow, data is too large")
type LimitWriter struct {
io.Writer
N int64
written int64
}
func (l *LimitWriter) Write(p []byte) (n int, err error) {
if l.written+int64(len(p)) >= l.N {
return 0, ErrWriteOverflow
}
n, err = l.Writer.Write(p)
l.written += int64(n)
return
}