net/http 下載 在golang中,如果我們要下載一個文件,最簡單的就是先用http.get()方法創建一個遠程的請求後,後面可使用ioutil.WriteFile()等將請求內容直接寫到文件中。 但是你會發現,上面的操作方式會有一個小問題,那就是下載小文件還行,如果是大的文件的話,可能會出現 ...
net/http 下載
在golang中,如果我們要下載一個文件,最簡單的就是先用http.get()方法創建一個遠程的請求後,後面可使用ioutil.WriteFile()等將請求內容直接寫到文件中。
func DownFile() {
url :="http://wx.qlogo.cn/Vaz7vE1/64"
resp ,err := http.Get(url)
if err != nil {
fmt.Fprint(os.Stderr ,"get url error" , err)
}
defer resp.Body.Close()
data ,err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
_ =ioutil.WriteFile("/tmp/icon_wx.png", data, 0755)
}
但是你會發現,上面的操作方式會有一個小問題,那就是下載小文件還行,如果是大的文件的話,可能會出現記憶體不足的問題,因為它是需要先把請求內容全部讀取到記憶體中,然後再寫入到文件中的。
那如果要下載大文件或者複製大文件,應該怎麼辦呢? 其實,Golang中就提供了 io.copy
方法,它就是在文件指針之間直接複製的,不用全讀入記憶體,可解決這樣的問題。
io.copy
我們先看下原型聲明
func Copy(dst Writer, src Reader) (written int64, err error) {
return copyBuffer(dst, src, nil)
}
func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {
....
if buf == nil {
size := 32 * 1024
if l, ok := src.(*LimitedReader); ok && int64(size) > l.N {
if l.N < 1 {
size = 1
} else {
size = int(l.N)
}
}
buf = make([]byte, size)
}
它是將源複製到目標,並且是按預設的緩衝區32k迴圈操作的,不會將內容一次性全寫入記憶體中,這樣就能解決大文件的問題。
我們再用 io.copy
來實現一下吧。
func DownFile() {
url :="http://wx.qlogo.cn/Vaz7vE1/64"
resp ,err := http.Get(url)
if err != nil {
fmt.Fprint(os.Stderr ,"get url error" , err)
}
defer resp.Body.Close()
out, err := os.Create("/tmp/icon_wx_2.png")
wt :=bufio.NewWriter(out)
defer out.Close()
n, err :=io.Copy(wt, resp.Body)
fmt.Println("write" , n)
if err != nil {
panic(err)
}
wt.Flush()
}
同理,如果我們要複製大文件也可以用 io.copy
這個,防止產生記憶體溢出。