有没有一种方法可以使用 Go 下载一个大型文件,将内容直接存储到一个文件中,而不是在将其写入文件之前将其全部存储在内存中?因为文件非常大,在写入文件之前将它们全部存储在内存中将耗尽所有内存。
我假设你的意思是通过 http 下载(为简洁起见省略了错误检查) :
import ("net/http"; "io"; "os") ... out, err := os.Create("output.txt") defer out.Close() ... resp, err := http.Get("http://example.com/") defer resp.Body.Close() ... n, err := io.Copy(out, resp.Body)
Http://http://http://http://http://http://.Response 的 Body 是一个 Reader,因此您可以使用任何带有 Reader 的函数,例如,一次读取一个块,而不是一次全部读取。在这个特定的例子中,io.Copy()为您完成了基础工作。
io.Copy()
这是一个样本。 https://github.com/thbar/golang-playground/blob/master/download-files.go
还有,我给你一些密码也许能帮到你。
密码:
func HTTPDownload(uri string) ([]byte, error) { fmt.Printf("HTTPDownload From: %s.\n", uri) res, err := http.Get(uri) if err != nil { log.Fatal(err) } defer res.Body.Close() d, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatal(err) } fmt.Printf("ReadFile: Size of download: %d\n", len(d)) return d, err } func WriteFile(dst string, d []byte) error { fmt.Printf("WriteFile: Size of download: %d\n", len(d)) err := ioutil.WriteFile(dst, d, 0444) if err != nil { log.Fatal(err) } return err } func DownloadToFile(uri string, dst string) { fmt.Printf("DownloadToFile From: %s.\n", uri) if d, err := HTTPDownload(uri); err == nil { fmt.Printf("downloaded %s.\n", uri) if WriteFile(dst, d) == nil { fmt.Printf("saved %s as %s\n", uri, dst) } } }
Steve M 的回答的更具描述性的版本。
import ( "os" "net/http" "io" ) func downloadFile(filepath string, url string) (err error) { // Create the file out, err := os.Create(filepath) if err != nil { return err } defer out.Close() // Get the data resp, err := http.Get(url) if err != nil { return err } defer resp.Body.Close() // Check server response if resp.StatusCode != http.StatusOK { return fmt.Errorf("bad status: %s", resp.Status) } // Writer the body to file _, err = io.Copy(out, resp.Body) if err != nil { return err } return nil }
上面使用 io.Copy选择的答案正是您所需要的,但是如果您对其他特性感兴趣,比如恢复中断的下载、自动命名文件、校验和验证或监视多个下载的进度,请检查 抓住包。
io.Copy