使用io.Pipe()读/​​写golang下载zip文件

时间:2016-11-10 19:59:16

标签: go zip pipe streamreader writer

我正在尝试使用golang中的io.Pipe()函数流出zip文件的字节。我正在使用管道读取器读取zip中每个文件的字节,然后将它们流出并使用管道写入器在响应对象中写入字节。

func main() {
  r, w := io.Pipe()
 // go routine to make the write/read non-blocking
  go func() {

    defer w.Close()

    bytes, err := ReadBytesforEachFileFromTheZip() 
    err := json.NewEncoder(w).Encode(bytes)
    handleErr(err)
  }()

这不是一个有效的实现,而是我想要实现的结构。我不想使用ioutil.ReadAll,因为文件非常大,而Pipe()将帮助我避免将所有数据都带入内存。有人可以使用io.Pipe()来帮助实现工作吗?

1 个答案:

答案 0 :(得分:-1)

我使用golang io.Pipe()使其工作.Tipewriter以块的形式将字节写入管道,而另一端的pipeReader读取器。使用go-routine的原因是在从管道发生同时读取的同时进行非阻塞写操作。

注意:关闭管道编写器(w.Close())以在流上发送EOF非常重要,否则它将不会关闭流。

func DownloadZip() ([]byte, error) {
    r, w := io.Pipe()

    defer r.Close()
    defer w.Close()

    zip, err := os.Stat("temp.zip")
    if err != nil{
        return nil, err
    }

    go func(){

        f, err := os.Open(zip.Name())
        if err != nil {
            return

        }

        buf := make([]byte, 1024)
        for {
            chunk, err := f.Read(buf)
            if err != nil && err != io.EOF {
                panic(err)
            }
            if chunk == 0 {
                break
            }

            if _, err := w.Write(buf[:chunk]); err != nil{
                return
            }

        }

        w.Close()
    }()

    body, err := ioutil.ReadAll(r)
    if err != nil {
        return nil, err
    }
    return body, nil

}

如果有人有其他办法,请告诉我。