如何将io.ReadCloser流式传输到http.ResponseWriter中

huangapple go评论98阅读模式
英文:

How to stream an io.ReadCloser into a http.ResponseWriter

问题

我有一个客户端,它发送一个下载文件的请求,Web服务器将该请求转发到实际保存文件的资源服务器。资源服务器返回的 *http.Response 对象具有一个从资源服务器流式传输文件内容的 Body io.ReaderCloser。但是,我想将该内容写入来自客户端的原始 http.ResponseWriter。查看 http.ResponseWriter 接口,它只包含一个接受字节切片的 Write 方法,这让我想到将文件内容读取到缓冲区中,然后将其放入 http.ResponseWriter 的 Write 方法中是将文件内容返回给客户端的唯一方法。但我不想这样做,因为这样非常低效,最好的方式是通过我的 Web 服务器进行流式传输。这种方式可行吗?

以下是一些示例代码:

getFile() *http.Response {
    // 向资源服务器发送请求并返回响应对象
}

// 处理来自客户端的请求
http.HandleFunc("/getFile", func(w http.ResponseWriter, r *http.Request){
    res := getFile()
    // 如何在不使用缓冲区的情况下将 res.Body 流式传输到 w?
})

请注意,我只会返回翻译好的部分,不会回答关于翻译的问题。

英文:

I have a client which makes a request to download a file, the web server forwards this request on to the resource server that actually holds the file. The *http.Response back from the resource server has the Body io.ReaderCloser streaming the file contents from the resource server. But I'm then at the point where I want to start writing that into the original http.ResponseWriter that came from the client. Looking at the http.ResponseWriter interface it only contains a Write method which takes a slice of bytes, which makes me think that the only way to get the file contents back to the client is to read the Body io.ReaderCloser into a buffer and then put that into the http.ResponseWriter's Write method. which I dont want to do since that is hugely inefficient and it would be much better to stream it through my web server. Is this possible?

here is some code to illustrate:

getFile() *http.Response {
    //make a request to resource server and return the response object
}

// handle request from client
http.HandleFunc("/getFile", func(w http.ResponseWriter, r *http.Request){
	res := getFile()
    //how can I stream res.Body into w without buffering ?
})

答案1

得分: 19

你可以使用io.Copy()来实现这个功能。

> Copy()函数会从源(src)复制数据到目标(dst),直到源(src)达到文件末尾(EOF)或者发生错误。它会返回复制的字节数以及在复制过程中遇到的第一个错误(如果有的话)。

n, err := io.Copy(w, res.Body)
// 检查错误

另外需要注意的是,Copy()函数不会返回io.EOF,而是返回nil。因为如果它能够将所有数据从源(src)复制到目标(dst),直到源(src)报告io.EOF,这并不被视为错误。

英文:

You can use io.Copy() which does exactly this.

> Copy copies from src to dst until either EOF is reached on src or an error occurs. It returns the number of bytes copied and the first error encountered while copying, if any.

n, err := io.Copy(w, res.Body)
// check err

Also note that Copy() will not return io.EOF but nil because if it can "copy" everything until src reports io.EOF, that is not considered an error.

huangapple
  • 本文由 发表于 2016年1月18日 20:56:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/34855343.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定