如何在不分配内存的情况下压缩并发布文件

dyr*_*kin 4 gzip http go

有谁知道如何打开文件、随时随地对其进行 gzip 并使用发布请求将其发送到服务器?

我有一个文件是阅读器。另外,我有http.Post()一个函数可以将阅读器作为第三个参数传递。但gzip.NewWriter()期待一个作家并返回一个作家。

我知道我可以创建一些中间缓冲区来连接这一切,但我不想分配太多内存,因为这些文件可能很大。有没有办法制作这个管道并将其传递给 HTTP post 请求?

Pim*_*Pim 6

是的,io.Pipe

    reader, writer := io.Pipe()
    go func() {
        defer w.Close()

        gw := gzip.NewWriter(w)
        defer gw.Close()

        gw.Write( []byte("replace with your data"))
    }()

    http.Post("some.url", "application/zip", reader)
Run Code Online (Sandbox Code Playgroud)


gop*_*her 6

其他答案概述了如何使用 io.Pipe。这个答案显示了更多细节,特别是在错误处理方面。

func gzFileReader(fname string) (io.ReadCloser, error) {
    f, err := os.Open(fname)
    if err != nil {
        return nil, err
    }

    // Use io.Pipe and a goroutine to create reader
    // on data written by the appliation.
    r, w := io.Pipe()
    go func() {
        // Always close the file.
        defer f.Close()

        // Copy file through gzip to pipe writer.
        gzw := gzip.NewWriter(w)
        _, err := io.Copy(gzw, f)

        // Use CloseWithError to propgate errors back to
        // the main goroutine.
        if err != nil {
            w.CloseWithError(err)
            return
        }

        // Flush the gzip writer.
        w.CloseWithError(gzw.Close())
    }()
    return r, nil
}
Run Code Online (Sandbox Code Playgroud)

使用这样的函数:

body, err := gzFileReader("example.txt")
if err != nil {
    log.Fatal(err)
}
defer body.Close()

req, err := http.NewRequest("POST", "http://example.com/", body)
if err != nil {
    log.Fatal(err)
}
req.Header.Set("Content-Encoding", "gzip")
resp, err := http.DefaultClient.Do(req)
Run Code Online (Sandbox Code Playgroud)