Skip to content

Instantly share code, notes, and snippets.

@philippdrebes
Created March 20, 2018 19:45
Show Gist options
  • Save philippdrebes/dc817093c273f49b5b80277f197259ee to your computer and use it in GitHub Desktop.
Save philippdrebes/dc817093c273f49b5b80277f197259ee to your computer and use it in GitHub Desktop.
download progress in go
// 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
}
// 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
}
func download(url string, output string) (err error) {
// create the file
out, err := os.Create(output)
if err != nil {
return err
}
defer out.Close()
response, err := http.Get(url)
if err != nil {
return err
}
defer response.Body.Close()
readerpt := &PassThru{Reader: response.Body, length: response.ContentLength}
// check server response
if response.StatusCode != http.StatusOK {
return fmt.Errorf("bad status: %s", response.Status)
}
// Writer the body to file
_, err = io.Copy(out, readerpt)
if err != nil {
return err
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment