将http.Response导入http.ResponseWriter

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

Piping http.Response to http.ResponseWriter

问题

我正在尝试将从API接收到的文件通过管道直接返回给用户,而无需将其全部存储在内存中。

在我的搜索过程中,我遇到了不同的概念和想法,比如io.Copyio.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()	
}

huangapple
  • 本文由 发表于 2015年3月6日 10:39:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/28891531.html
匿名

发表评论

匿名网友

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

确定