跟踪和显示下载文件摘要(百分比) - Go lang

Gab*_*ira 3 arrays io byte go

我正在做一个通过传递的url参数下载文件的过程.下载正在正常完成,但我不能做的是打印下载完成百分比的摘要.( 每一秒 )

我已经建立了一个模拟类型的这个摘要,但它没有下载任何东西,它只是为了表明我想要它.

我试图将io.copy带入我的源代码中,这样我就可以在复制完成时将其更改为ant print,但它失败了.

有人能帮我吗?谢谢

 package main

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

    func downloadFromUrl(url string) {
        tokens := strings.Split(url, "/")
        fileName := tokens[len(tokens)-1]
        fmt.Println("Downloading", url, "to", fileName)

    //create file
    output, err := os.Create(fileName)
    if err != nil {
        fmt.Println("Error while creating", fileName, "-", err)
        return
    }
    fmt.Println("Creating", fileName)
    defer output.Close()

    //get url
    response, err := http.Get(url)
    if err != nil {
        fmt.Println("Error while downloading", url, "-", err)
        return
    }           
    defer response.Body.Close()

    //copy and bytes        
    n, err := io.Copy(output, response.Body)
    if err != nil {
        fmt.Println("Error while downloading", url, "-", err)
        return
    }

        //track progress
        for i := 1; float64(i) < float64(n); i++ {
            fmt.Println("",float64(i),float64(n))
            percent := float64(i) / (float64(n) / float64(100))
            percentTot := fmt.Sprintf(" %#.02f%% ", percent)
            fmt.Println(percentTot,"downloaded\n")
            //time.Sleep(3000 * time.Millisecond)
        }   


    }

    func main() {
        //read args 
        args := os.Args

        //loop args
        for i := 1; i < len(args); i++ {
            url := args[i]
            //call download         
            downloadFromUrl(url)        
        }
    }


**Output:**
go run main.go http://download.geonames.org/export/dump/AD.zip
Downloading http://download.geonames.org/export/dump/AD.zip to AD.zip
Creating AD.zip
 1 64639
 0.00%  downloaded

 2 64639
 0.00%  downloaded

 3 64639
 0.00%  downloaded

 4 64639
 0.01%  downloaded

 5 64639
 0.01%  downloaded
Run Code Online (Sandbox Code Playgroud)

Von*_*onC 7

我在我的senvgo项目中用io.Reader包装器完成了这个

// PassThru wraps an existing io.Reader.
//
// It simply forwards the Read() call, while displaying
// the results from individual calls to it.
type PassThru struct {
    io.Reader
    total    int64 // Total # of bytes transferred
    length   int64 // Expected length
    progress float64
}
Run Code Online (Sandbox Code Playgroud)

Read()在那个包装器上定义一个方法(使它成为一个io.Reader)

// Read 'overrides' the underlying io.Reader's Read method.
// This is the one that will be called by io.Copy(). We simply
// use it to keep track of byte counts and then forward the call.
func (pt *PassThru) Read(p []byte) (int, error) {
    n, err := pt.Reader.Read(p)
    if n > 0 {
        pt.total += int64(n)
        percentage := float64(pt.total) / float64(pt.length) * float64(100)
        i := int(percentage / float64(10))
        is := fmt.Sprintf("%v", i)
        if percentage-pt.progress > 2 {
            fmt.Fprintf(os.Stderr, is)
            pt.progress = percentage
        }
    }

    return n, err
}
Run Code Online (Sandbox Code Playgroud)

并使用它io.Reader来读取Response(http请求的结果):

client := &http.Client{
    CheckRedirect: redirectPolicyFunc,
}
response, err := client.Get("http://example.com/something/large.zip")
defer response.Body.Close()
readerpt := &PassThru{Reader: response.Body, length: response.ContentLength}
body, err := ioutil.ReadAll(readerpt)
Run Code Online (Sandbox Code Playgroud)

ReadAll()调用触发实际下载,PassThru.Read()并将打印下载的%与预期长度(response.ContentLength)


启示: