英文:
Piping http.Response to http.ResponseWriter
问题
我正在尝试将从API接收到的文件通过管道直接返回给用户,而无需将其全部存储在内存中。
在我的搜索过程中,我遇到了不同的概念和想法,比如io.Copy
、io.Pipe()
等等。我不确定哪个是正确的解决方案。
例如,io.Pipe()
似乎是用于在现场创建新的读取器和写入器,而不是已经存在的读取器和写入器。
英文:
I'm trying to pipe a file that I receive from an API back to the user without having to store it all in memory.
I've come across different concepts/ideas across my search, such as io.Copy
, io.Pipe()
, etc. I'm not sure which one is the correct solution.
For example, io.Pipe()
seems like it's for if someone is creating a new reader and writer on the spot, not ones that already exist.
答案1
得分: 21
io.Copy
是解决这个问题的方法,代码大致如下:
func pipeReq(rw http.ResponseWriter, req *http.Request) {
resp, err := http.Get(".....")
if err != nil {
// 处理错误
return
}
rw.Header().Set("Content-Type", resp.Header.Get("Content-Type"))
rw.Header().Set("Content-Length", resp.Header.Get("Content-Length"))
io.Copy(rw, resp.Body)
resp.Body.Close()
}
//编辑:之前理解错了问题,现在修正了代码。
英文:
io.Copy
is the way to go for that, something along the lines of:
func pipeReq(rw http.ResponseWriter, req *http.Request) {
resp, err := http.Get(".....")
if err != nil{
//handle the error
return
}
rw.Header().Set("Content-Type", resp.Header.Get("Content-Type"))
rw.Header().Set("Content-Length", resp.Header.Get("Content-Length"))
io.Copy(rw, resp.Body)
resp.Body.Close()
}
//edit: misread the question, fixed the code now.
答案2
得分: 0
@OneOfOne的回答很好,但有一个小的改进是使用io.CopyBuffer
。CopyBuffer与Copy相同,只是它通过提供的缓冲区(如果需要)进行分段,而不是分配临时缓冲区。
func pipeReq(rw http.ResponseWriter, req *http.Request) {
resp, err := http.Get(".....")
if err != nil{
//处理错误
return
}
rw.Header().Set("Content-Type", resp.Header.Get("Content-Type"))
rw.Header().Set("Content-Length", resp.Header.Get("Content-Length"))
buf := make([]byte, 8)
if _, err := io.CopyBuffer(rw, resp.Body, buf); err != nil {
//处理错误
return
}
resp.Body.Close()
}
英文:
@OneOfOne's answer is great but one small improvement is to use io.CopyBuffer
. CopyBuffer is identical to Copy except that it stages through the provided buffer (if one is required) rather than allocating a temporary one
func pipeReq(rw http.ResponseWriter, req *http.Request) {
resp, err := http.Get(".....")
if err != nil{
//handle the error
return
}
rw.Header().Set("Content-Type", resp.Header.Get("Content-Type"))
rw.Header().Set("Content-Length", resp.Header.Get("Content-Length"))
buf := make([]byte, 8)
if _, err := io.CopyBuffer(rw, resp.Body, buf); err != nil {
// handle the error
return
}
resp.Body.Close()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论