How to print the bytes while the file is being downloaded ? -golang

后端 未结 4 1992
无人共我
无人共我 2021-01-31 06:29

I\'m wondering if it\'s possible to count and print the number of bytes downloaded while the file is being downloaded.

out, err := os.Create(\"file.txt\")
    d         


        
4条回答
  •  时光取名叫无心
    2021-01-31 07:24

    Other answers have explained about PassThru. Just provide a full example with callback function base on Dave Jack's answer.

    package main
    
    import (
        "fmt"
        "io"
        "net/http"
        "os"
        "strconv"
    )
    
    // writeCounter counts the number of bytes written to it.
    type writeCounter struct {
        total      int64 // total size
        downloaded int64 // downloaded # of bytes transferred
        onProgress func(downloaded int64, total int64)
    }
    
    // Write implements the io.Writer interface.
    //
    // Always completes and never returns an error.
    func (wc *writeCounter) Write(p []byte) (n int, e error) {
        n = len(p)
        wc.downloaded += int64(n)
        wc.onProgress(wc.downloaded, wc.total)
        return
    }
    
    func newWriter(size int64, onProgress func(downloaded, total int64)) io.Writer {
        return &writeCounter{total: size, onProgress: onProgress}
    }
    
    func main() {
        client := http.DefaultClient
        url := "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4"
        saveTo := "/Users/tin/Desktop/ForBiggerFun.mp4"
    
        download(client, url, saveTo, func(downloaded, total int64) {
            fmt.Printf("Downloaded %d bytes for a total of %d\n", downloaded, total)
        })
    }
    
    func download(client *http.Client, url, filePath string, onProgress func(downloaded, total int64)) (err error) {
        // Create file writer
        file, err := os.Create(filePath)
        if err != nil {
            return
        }
        defer file.Close()
    
        // Determinate the file size
        resp, err := client.Head(url)
        if err != nil {
            return
        }
        contentLength := resp.Header.Get("content-length")
        length, err := strconv.Atoi(contentLength)
        if err != nil {
            return
        }
    
        // Make request
        resp, err = client.Get(url)
        if err != nil {
            return
        }
        defer resp.Body.Close()
    
        // pipe stream
        body := io.TeeReader(resp.Body, newWriter(int64(length), onProgress))
        _, err = io.Copy(file, body)
        return err
    }
    

提交回复
热议问题