英文:
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()	
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论