133 votes

Comment télécharger efficacement un gros fichier en utilisant Go ?

Existe-t-il un moyen de télécharger un gros fichier à l'aide de Go qui stocke le contenu directement dans un fichier au lieu de le stocker entièrement en mémoire avant de l'écrire dans un fichier ? Comme le fichier est très volumineux, le stocker entièrement en mémoire avant de l'écrire dans un fichier va utiliser toute la mémoire.

246voto

Steve M Points 4137

Je suppose que vous voulez dire télécharger via http (les contrôles d'erreur sont omis pour des raisons de brièveté) :

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)

Le corps de http.Response est un lecteur, vous pouvez donc utiliser toutes les fonctions qui prennent un lecteur, pour, par exemple, lire un morceau à la fois plutôt que tous en même temps. Dans ce cas précis, io.Copy() fait le travail pour vous.

76voto

Pablo Karlsson Points 955

Une version plus descriptive de La réponse de 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
}

17voto

Ryan Armstrong Points 189

La réponse sélectionnée ci-dessus en utilisant io.Copy est exactement ce dont vous avez besoin, mais si vous êtes intéressé par des fonctionnalités supplémentaires telles que la reprise des téléchargements interrompus, l'attribution automatique d'un nom aux fichiers, la validation de la somme de contrôle ou le suivi de la progression de plusieurs téléchargements, consultez l'option saisir paquet.

-6voto

TeeTracker Points 692
  1. En voici un exemple. https://github.com/thbar/golang-playground/blob/master/download-files.go

  2. Je vous donne aussi quelques codes qui pourraient vous aider.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X