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.
Réponses
Trop de publicités?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.
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
}
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.
-
En voici un exemple. https://github.com/thbar/golang-playground/blob/master/download-files.go
-
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)
}
}
}