进度条

作者: 司空儿 | 来源:发表于2019-11-13 13:54 被阅读0次

    整个实现中,最重要的是 WriteCounter 这个结构体,这个结构体下的 Write(p []byte) 方法的参数 p 就是每段读取的内容。

    
    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
    }
    

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

    相关文章

      网友评论

          本文标题:进度条

          本文链接:https://www.haomeiwen.com/subject/vtvhictx.html