@@ -8,7 +8,11 @@ import (
88 "net/http"
99 "os"
1010 "path/filepath"
11+ "sync/atomic"
1112 "time"
13+
14+ "github.com/cenkalti/log"
15+ "github.com/paulbellamy/ratecounter"
1216)
1317
1418type Download struct {
@@ -99,8 +103,11 @@ func (d *Download) Run(ctx context.Context) error {
99103 trw := & TimerResetWriter {timer : time .AfterFunc (defaultTimeout , cancel )}
100104 tr := io .TeeReader (rc , trw )
101105
106+ pr := NewProgressReader (tr , d .state .Offset , d .state .Size , d .String ())
107+ go pr .Run ()
102108 remaining := d .state .Size - d .state .Offset
103- n , copyErr := io .CopyN (wc , tr , remaining )
109+ n , copyErr := io .CopyN (wc , pr , remaining )
110+ pr .Close ()
104111
105112 err = wc .Close ()
106113 if err != nil {
@@ -167,3 +174,48 @@ func (w *TimerResetWriter) Write(p []byte) (int, error) {
167174 w .timer .Reset (defaultTimeout )
168175 return len (p ), nil
169176}
177+
178+ type ProgressReader struct {
179+ r io.Reader
180+ offset int64
181+ size int64
182+ prefix string
183+ counter * ratecounter.RateCounter
184+ closeC chan struct {}
185+ }
186+
187+ func NewProgressReader (r io.Reader , offset , size int64 , prefix string ) * ProgressReader {
188+ return & ProgressReader {
189+ r : r ,
190+ offset : offset ,
191+ size : size ,
192+ prefix : prefix ,
193+ counter : ratecounter .NewRateCounter (time .Second ),
194+ closeC : make (chan struct {}),
195+ }
196+ }
197+
198+ func (r * ProgressReader ) Read (p []byte ) (int , error ) {
199+ n , err := r .r .Read (p )
200+ r .counter .Incr (int64 (n ))
201+ atomic .AddInt64 (& r .offset , int64 (n ))
202+ return n , err
203+ }
204+
205+ func (r * ProgressReader ) Run () {
206+ for {
207+ select {
208+ case <- time .After (time .Second ): // TODO use time.Ticker
209+ offset := atomic .LoadInt64 (& r .offset )
210+ progress := (offset * 100 ) / r .size
211+ speed := r .counter .Rate () / 1024
212+ log .Infof ("%s %d%% %dKB/s" , r .prefix , progress , speed )
213+ case <- r .closeC :
214+ return
215+ }
216+ }
217+ }
218+
219+ func (r * ProgressReader ) Close () {
220+ close (r .closeC )
221+ }
0 commit comments