目标
使用go原生http库下载时,显示实时下载进度。
How
Go的Http是一个流,通过截取流的信息可以完成显示下载进度的目的。
- 首先定义一个接口
1
2
3
4
|
type Counter interface {
Write(p []byte) (int, error)
SetTotal(total int64)
}
|
- 定义接口实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
type WriteCounter struct {
Total int64 `json:"total"`
Current int64 `json:"current"`
Rate int64 `json:"rate"`
Package string `json:"package"`
}
func (w *WriteCounter) Write(p []byte) (int, error) {
n := len(p)
w.Current += int64(n)
w.Rate = w.Current * 100 / w.Total
fmt.Printf("\rDownloading[%s][ %s%% ][%d/%d] B complete",w.Package,w.Rate, w.Current,w.Total)
return n, nil
}
func (w *WriteCounter) SetTotal(total int64) {
d.Total = total
}
|
- 定义下载逻辑
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
|
func Download(counter IOCounter, url, path string) error {
resp, err := http.Get(url)
if err != nil {
logger.Errorf("request %s error: %v", url, err)
return err
}
defer func() {
closeError := resp.Body.Close()
if closeError != nil {
logger.Errorf("close error: %v", closeError)
return
}
}()
counter.SetTotal(resp.ContentLength)
out, err := os.Create(path)
if err != nil {
return err
}
defer out.Close()
if _, err = io.Copy(out, io.TeeReader(resp.Body, counter)); err != nil {
logger.Errorf("write error: %v", err)
}
logger.Infof("download [ %v ]->[ %s ] success", url, path)
return nil
}
|