-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
123 lines (111 loc) · 2.9 KB
/
main.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
120
121
122
123
package main
import (
"fmt"
"github.com/levigross/grequests"
"os"
"path"
"runtime"
"strconv"
)
var downloadPath string
var downloadFile *os.File
var url string
func createFile(fileSize int64) (*os.File, error) {
//TODO 剩余空间检测
file, err := os.Create(downloadPath)
if err != nil {
fmt.Println("下载失败-创建文件失败")
return nil, err
}
err = file.Truncate(fileSize)
if err != nil {
fmt.Println(err.Error())
return nil, err
}
return file, nil
}
func download(startIndex int64, endIndex int64) error {
ua := "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36"
blockRange := "bytes=" + strconv.FormatInt(startIndex, 10) + "-" + strconv.FormatInt(endIndex, 10)
ro := &grequests.RequestOptions{Headers: map[string]string{"User-Agent": ua, "Range" : blockRange}}
resp, err := grequests.Get(url, ro)
if err != nil {
fmt.Println(err.Error())
return err
}
if resp.StatusCode == 206 {
err = writeFile(resp.Bytes(), startIndex)
if err != nil {
return err
}
}
return nil
}
func writeFile(content []byte, startIndex int64) error {
_, err := downloadFile.WriteAt(content, startIndex)
if err != nil {
return err
}
return nil
}
func run(blockSize int, threadsNum int, totalLength int) {
finishChan := make(chan int)
for i := 0; i < threadsNum; i++ {
startIndex := i * blockSize
endIndex := (i + 1) * blockSize - 1
if i == threadsNum- 1 {
endIndex = totalLength
}
go func(proc int) {
err := download(int64(startIndex), int64(endIndex))
if err != nil {
fmt.Println(err.Error())
finishChan <- 0
return
}
finishChan <- proc + 1
}(i)
}
for i := 0; i < threadsNum; i++ {
x := <-finishChan
if x == 0 {
fmt.Println("有错误")
}else {
fmt.Println(x, "段下载完成")
}
}
_ = downloadFile.Close()
}
func main() {
threadsNum := runtime.NumCPU() + 1
fmt.Println("线程数" , threadsNum)
url = "http://mirrors.163.com/archlinux/iso/latest/archlinux-2019.05.02-x86_64.iso.torrent"
downloadPath = path.Base(url) //todo 文件名检测
ua := "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36"
ro := &grequests.RequestOptions{Headers: map[string]string{"User-Agent": ua}}
resp, err := grequests.Head(url,ro)
if err != nil {
fmt.Println(err.Error())
return
}
//todo 多线程下载支持检测
str, ok := resp.Header["Content-Length"]
if resp.StatusCode == 200 && ok && len(str) == 1 {
contentLength, _ := strconv.Atoi(str[0])
if contentLength <= threadsNum* 1000 {
threadsNum = 1
}
blockSize := contentLength / threadsNum
f, err := createFile(int64(contentLength))
if err != nil {
fmt.Println("下载失败")
fmt.Println(err.Error())
f.Close()
return
}
downloadFile = f
run(blockSize, threadsNum, contentLength)
}else {
fmt.Println("下载失败")
}
}