如何获取压缩文件夹的大小



用例为:我想压缩一个文件夹,其中可以包含n个不同大小的文件。我想添加限制,比如如果zip大小>x(MB|GB(,则不创建zip并抛出错误。我试图在迭代文件夹后创建zip文件后获得zip文件的大小,但无法做到。请在此处寻求帮助。我使用io.writer来创建zip文件,而不是缓冲区。示例代码为

注意:当使用";buf:=new(字节.缓冲区(";但我想使用io.writer进行计算,如下所示

filepath-文件夹的路径downloadLimit-我想为下载的zip文件设置的限制。类似zip文件大小不应超过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
}

上面的函数创建zip文件,但我希望它在达到限制后立即停止创建并退出,或者至少获取创建的zip文件的大小

标准API没有提供io.Writer实现来实现这一点,afaik。它存在一个LimitReader,但它对您的情况用处不大,会导致我们编写相当复杂的代码。

相反,您可以编写自己的io.Writer包装器实现,以确保如果写入的字节总数超过某个长度,或者即将返回错误。

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
}

https://play.golang.org/p/ktgF-pOzFjm

以下是如何解决此问题的建议。代码中的解释。我认为在不执行实际压缩的情况下,没有(简单的(方法可以计算/估计未来zip文件的大小。

代码的第1行假设您已经有了要压缩的文件的某种字节表示。

func main() {       
// Create a buffer to write our archive to (in memory)
buf := new(bytes.Buffer)
// Create a new zip archive writer, that writes to our in memory buffer
archiveWriter := zip.NewWriter(buf)
// ensure to close your zip writer later
defer archiveWriter.Close()
// you probably want to do this in a loop and repeat for each file you want add to the zip archive
// this is the content of a file you want to zip / instead read it from disk with ioutil.ReadFile() or some other approach
dummyBytes := []byte("ThisCouldBeTheContentOfYourSourceFile")
fileWriter, _ := archiveWriter.Create("fileNameOfSourceFileInZip")
_, _ = fileWriter.Write(dummyBytes)


// validate the in memory representation of the zip file does not exceed your limit
if buf.Len() > 1000 {
// todo raise error
return
}

// write the zip file to the disk, you could ofc also use io.writer
_ = ioutil.WriteFile("TargetZipFile.zip", buf.Bytes(), 0644)
}

请注意,我没有实现任何错误处理——你可能想添加它。

最新更新