首页 > 解决方案 > 压缩目录并且没有将结果保存在文件系统中

问题描述

我可以使用类似于此处看到的 zip 编写器的逻辑来压缩文件。

这会导致在返回的对象中[]byte创建一个字节数组 ( )。bytes.Buffer我想知道是否有任何方法可以将这个“压缩”字节数组上传到一个 API 端点,该端点需要一个“multipart/form-data”请求主体(无需在本地保存)。

补充资料:

我有在压缩文件夹时使用它的代码。我能够使用此逻辑成功执行带有 zip 文件的 HTTP POST 请求到端点。

但是,不幸的是,这会将压缩文件保存在用户的本地文件系统中。我想尽量避免这种情况:)

标签: gozipfilesystemsgzip

解决方案


如果您想流式上传 zip,您应该可以使用io.Pipe. 以下是一个不完整且未经测试的示例,用于演示总体思路。要使其正常工作,您需要对其进行修改并可能修复您遇到的任何错误。

func UploadReader(r io.Reader) error {
    req, err := http.NewRequest("POST", "<UPLOAD_URL>", r)
    if err != nil {
        return err
    }

    // TODO set necessary headers (content type, auth, etc)

    res, err := http.DefaultClient.Do(req)
    if err != nil {
        return err
    } else if res.StatusCode != 200 {
        return errors.New("not ok")
    }
    return nil
}
func ZipDir(dir string, w io.Writer) error {
    zw := zip.NewWriter(w)
    defer zw.Close()

    return filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if !fi.Mode().IsRegular() {
            return nil
        }

        header, err := zip.FileInfoHeader(fi)
        if err != nil {
            return err
        }
        header.Name = path
        header.Method = zip.Deflate

        w, err := zw.CreateHeader(header)
        if err != nil {
            return err
        }

        f, err := os.Open(path)
        if err != nil {
            return err
        }
        defer f.Close()

        if _, err := io.Copy(w, f); err != nil {
            return err
        }
        return nil
    })
}
func UploadDir(dir string) error {
    r, w := io.Pipe()

    ch := make(chan error)
    wg := sync.WaitGroup{}

    wg.Add(1)
    go func() {
        defer wg.Done()
        defer w.Close()

        if err := ZipDir(dir, w); err != nil {
            ch <- err
        }
    }()

    wg.Add(1)
    go func() {
        defer wg.Done()
        defer r.Close()

        if err := UploadReader(r); err != nil {
            ch <- err
        }
    }()

    go func() {
        wg.Wait()
        close(ch)
    }()

    return <-ch
}

推荐阅读