(转) golang 带进度条下载

声明:内容源自网络,版权归原作者所有。若有侵权请联系我们

分别看此两个网址:

https://www.golangtc.com/t/5e229741b17a82532765a0fa

https://www.twle.cn/t/385

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "strings"
)

// WriteCounter counts the number of bytes written to it. It implements to the io.Writer
// interface and we can pass this into io.TeeReader() which will report progress on each
// write cycle.
type WriteCounter struct {
    Total uint64
}

func (wc *WriteCounter) Write(p []byte) (int, error) {
    n := len(p)
    wc.Total += uint64(n)
    wc.PrintProgress()
    return n, nil
}

func (wc WriteCounter) PrintProgress() {
    // Clear the line by using a character return to go back to the start and remove
    // the remaining characters by filling it with spaces
    fmt.Printf("\r%s", strings.Repeat(" ", 35))

    // Return again and print current status of download
    // We use the humanize package to print the bytes in a meaningful way (e.g. 10 MB)
    fmt.Printf("\rDownloading... %d B complete", wc.Total)
}

func main() {
    fmt.Println("Download Started")

    fileUrl := "https://dl.google.com/go/go1.11.1.src.tar.gz"
    err := DownloadFile("go1.11.1.src.tar.gz", fileUrl)
    if err != nil {
        panic(err)
    }

    fmt.Println("Download Finished")
}

// DownloadFile will download a url to a local file. It's efficient because it will
// write as it downloads and not load the whole file into memory. We pass an io.TeeReader
// into Copy() to report progress on the download.
func DownloadFile(filepath string, url string) error {

    // Create the file, but give it a tmp file extension, this means we won't overwrite a
    // file until it's downloaded, but we'll remove the tmp extension once downloaded.
    out, err := os.Create(filepath + ".tmp")
    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()

    // Create our progress reporter and pass it to be used alongside our writer
    counter := &WriteCounter{}
    _, err = io.Copy(out, io.TeeReader(resp.Body, counter))
    if err != nil {
        return err
    }

    // The progress use the same line so print a new line once it's finished downloading
    fmt.Print("\n")

    err = os.Rename(filepath+".tmp", filepath)
    if err != nil {
        return err
    }

    return nil
}

相关文章