This repository was archived by the owner on Nov 26, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathprogress.go
119 lines (101 loc) · 2.63 KB
/
progress.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Create a progress bar for applications that can keep track of a download in
// progress. The progress bar will be on a separate thread and will communicate
// with the main thread using delegates.
package main
import (
"fmt"
"io"
"net/http"
"os"
"strconv"
"time"
)
func main() {
download := NewDownload("https://download.mozilla.org/?product=firefox-28.0-SSL&os=osx&lang=en-US",
"firefox.dmg")
progressBar := ProgressBar{download}
progressBar.Start()
}
type Download struct {
File *os.File
Response *http.Response
ContentLength int
Done bool
}
func (download *Download) StartDownload() {
_, err := io.Copy(download.File, download.Response.Body)
if err != nil {
fmt.Println("Error:", err)
download.Done = true
return
}
download.Done = true
}
func NewDownload(url string, fileName string) *Download {
// Allocate memory for a new Download object
download := new(Download)
out, err := os.Create(fileName)
if err != nil {
fmt.Println("Error:", err)
}
download.File = out
response, err := http.Get(url)
if err != nil {
fmt.Println("Error:", err)
}
download.Response = response
download.ContentLength, _ = strconv.Atoi(response.Header.Get("content-length"))
download.Done = false
return download
}
func (download *Download) BytesDownloaded() int {
info, err := download.File.Stat()
if err != nil {
fmt.Println("Error:", err)
return 0
}
return int(info.Size())
}
type ProgressBar struct {
Download *Download
}
func (progressBar *ProgressBar) Start() {
// Run the download in a goroutine
go progressBar.Download.StartDownload()
progressBar.Show()
// Remember to close the file and connection!
progressBar.Download.Response.Body.Close()
progressBar.Download.File.Close()
}
func (progressBar *ProgressBar) Show() {
var progress int
totalBytes := int(progressBar.Download.ContentLength)
lastTime := false
// While the download is in progress, keep redrawing the progress bar
for !progressBar.Download.Done || lastTime {
// Start the progress bar - carriage return to overwrite previous iteration
fmt.Print("\r[")
bytesDone := progressBar.Download.BytesDownloaded()
progress = 40 * bytesDone / totalBytes
// Build the progress bar
for i := 0; i < 40; i++ {
if i < progress {
fmt.Print("=")
} else if i == progress {
fmt.Print(">")
} else {
fmt.Print(" ")
}
}
fmt.Print("] ")
fmt.Printf("%d/%dkB", bytesDone/1000, totalBytes/1000)
time.Sleep(100 * time.Millisecond)
// After the download completes, we need one more loop iteration
if progressBar.Download.Done && !lastTime {
lastTime = true
} else {
lastTime = false
}
}
fmt.Println()
}