🧱 Chunk is a download manager for slow and unstable servers
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Repo reorg

+4 -96
-79
example.go
··· 1 - package main 2 - 3 - import ( 4 - "context" 5 - "fmt" 6 - "time" 7 - ) 8 - 9 - func humanSize(s float64) string { 10 - size, unit := func(s float64) (float64, string) { 11 - m := []string{"B", "kB", "MB", "GB", "TB"} 12 - i := 0 13 - b := 1000.0 14 - for s >= b && i < len(m)-1 { 15 - s = s / b 16 - i++ 17 - } 18 - return s, m[i] 19 - }(s) 20 - return fmt.Sprintf("%.1f%s", size, unit) 21 - } 22 - 23 - type file struct{ total, done int64 } 24 - 25 - type downloadProgress struct { 26 - files map[string]file 27 - startedAt time.Time 28 - close context.CancelFunc 29 - } 30 - 31 - func (p *downloadProgress) total() (t int64) { 32 - for _, f := range p.files { 33 - t += f.total 34 - } 35 - return 36 - } 37 - 38 - func (p *downloadProgress) done() (d int64) { 39 - for _, f := range p.files { 40 - d += f.done 41 - } 42 - return 43 - } 44 - 45 - func (p *downloadProgress) String() string { 46 - perc := float64(p.done()) / float64(p.total()) 47 - speed := float64(p.done()) / time.Since(p.startedAt).Seconds() 48 - return fmt.Sprintf( 49 - "Downloading %s of %s\t%.2f%%\t%s/s", 50 - humanSize(float64(p.done())), 51 - humanSize(float64(p.total())), 52 - perc*100, 53 - humanSize(speed), 54 - ) 55 - } 56 - 57 - func (p *downloadProgress) update(d DownloadStatus) { 58 - p.files[d.DownloadedFilePath] = file{d.FileSizeBytes, d.DownloadedFileBytes} 59 - if p.done() == p.total() { 60 - p.close() 61 - } 62 - } 63 - 64 - func NewProgress() *downloadProgress { 65 - ctx, cancel := context.WithCancel(context.Background()) 66 - bar := downloadProgress{make(map[string]file), time.Now(), cancel} 67 - tick := time.Tick(1 * time.Second) 68 - go func() { 69 - for { 70 - select { 71 - case <-tick: 72 - fmt.Printf("\r%s", bar.String()) 73 - case <-ctx.Done(): 74 - return 75 - } 76 - } 77 - }() 78 - return &bar 79 - }
+1 -14
main.go downloader.go
··· 1 - package main 1 + package chunk 2 2 3 3 import ( 4 4 "bytes" 5 5 "context" 6 6 "fmt" 7 - "log" 8 7 "net/http" 9 8 "os" 10 9 "path/filepath" ··· 304 303 305 304 return &d 306 305 } 307 - 308 - func main() { 309 - chunk := DefaultDownloader() 310 - prog := NewProgress() 311 - for status := range chunk.Download(os.Args[1:len(os.Args)]...) { 312 - if status.Error != nil { 313 - log.Fatal(status.Error) 314 - } 315 - prog.update(status) 316 - } 317 - fmt.Printf("\r%s\nDownloaded to: %s", prog.String(), os.TempDir()) 318 - }
+1 -1
main_test.go downloader_test.go
··· 1 - package main 1 + package chunk 2 2 3 3 import ( 4 4 "context"
+1 -1
progress.go
··· 1 - package main 1 + package chunk 2 2 3 3 import ( 4 4 "encoding/gob"
+1 -1
progress_test.go
··· 1 - package main 1 + package chunk 2 2 3 3 import ( 4 4 "os"