program tip

Go를 사용하여 대용량 파일을 효율적으로 다운로드하려면 어떻게해야합니까?

radiobox 2020. 8. 20. 08:09
반응형

Go를 사용하여 대용량 파일을 효율적으로 다운로드하려면 어떻게해야합니까?


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.Response의 본문은 리더이므로 한 번에 모두가 아니라 한 번에 한 번에 덩어리를 읽는 등 리더를 사용하는 모든 기능을 사용할 수 있습니다. 이 특정한 경우에, io.Copy()당신을 위해 gruntwork합니다.


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
}

The answer selected above using io.Copy is exactly what you need, but if you are interested in additional features like resuming broken downloads, auto-naming files, checksum validation or monitoring progress of multiple downloads, checkout the grab package.


  1. Here is a sample. https://github.com/thbar/golang-playground/blob/master/download-files.go

  2. Also I give u some codes might help you.

code:

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)
        }
    }
}

참고URL : https://stackoverflow.com/questions/11692860/how-can-i-efficiently-download-a-large-file-using-go

반응형