dousou1878 2019-04-11 02:07
浏览 101
已采纳

使用缓冲区作为输出时,压缩的文件夹已损坏

I'm trying to write the zip file to a buffer instead of a file to eventually pass it to the http response. Below is the code to simulate that.

package main

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

func main() {
    data, err := zipit("myfolder")
    if err != nil {
        panic(err)
    }
    ioutil.WriteFile("output.zip", data, os.ModePerm)
}

func zipit(source string) ([]byte, error) {
    buf := new(bytes.Buffer)
    archive := zip.NewWriter(buf)
    defer archive.Close()
    info, err := os.Stat(source)
    if err != nil {
        return nil, nil
    }

    var baseDir string
    if info.IsDir() {
        baseDir = filepath.Base(source)
    }
    filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }

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

        if baseDir != "" {
            header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
        }

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

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

        if info.IsDir() {
            return nil
        }

        file, err := os.Open(path)
        if err != nil {
            return err
        }
        defer file.Close()
        _, err = io.Copy(writer, file)
        return err
    })
    return buf.Bytes(), err
}

However the output of this zip process is corrupted. If I use a file instead of a buffer it works thought.

zipfile, err := os.Create(target)
if err != nil {
    return err
}
defer zipfile.Close()

archive := zip.NewWriter(zipfile)
defer archive.Close()

Both os.File and bytes.Buffer implements io.Writer interface and eligible to be passed as a writer to zip.NewWrite() method.

Any direction to solve this would be appreciated.

  • 写回答

1条回答 默认 最新

  • dousenjue3214 2019-04-11 02:28
    关注

    You read the buffer before you've closed the zip.Writer, so any final data is needs to flush to the buffer has gotten lost. You should remove the defer archive.Close() and instead close the archive before getting the bytes out of the buffer. e.g.

        err = archive.Close()
        return buf.Bytes(), err
    

    It works in your file case because you defer closing the file. The defer's will be applied last in first out, so the archive gets closed before the file is closed.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

    报告相同问题?

    悬赏问题

    • ¥15 java连接sqlserver有问题
    • ¥15 yolov8 如何调cfg参数
    • ¥15 这个四人抢答器代码哪儿有问题?仿真程序怎么写?
    • ¥15 burpsuite密码爆破
    • ¥15 关于#ubuntu#的问题,如何解决?(相关搜索:移动硬盘)
    • ¥15 scikit安装之后import不了
    • ¥15 Ros2编译一个使用opencv的c++节点的时候,报了这个错误,请问怎么解决啊
    • ¥15 人脸识别相关算法 YOLO,AI等
    • ¥15 spark问题方便加V17675797079
    • ¥15 Python代码不打印的原因