feat: integration torrent (#30)

This commit is contained in:
monkeyWie authored and GitHub committed 2022-08-11 14:38:16 +08:00
1 parent 43378c7dc8
commit 034137322f
20 files changed
+925 -139

No files matched your search

+45 -23
View File
@@ -39,29 +39,14 @@ type Fetcher struct {
res *base.Resource
opts *base.Options
status base.Status
clients []*http.Response
chunks []*Chunk
clients []*http.Response
ctx context.Context
cancel context.CancelFunc
pauseCh chan interface{}
}
func NewFetcher() *Fetcher {
return &Fetcher{
DefaultFetcher: new(fetcher.DefaultFetcher),
pauseCh: make(chan interface{}),
}
}
var protocols = []string{"HTTP", "HTTPS"}
func FetcherBuilder() ([]string, func() fetcher.Fetcher) {
return protocols, func() fetcher.Fetcher {
return NewFetcher()
}
}
func (f *Fetcher) Resolve(req *base.Request) (*base.Resource, error) {
httpReq, err := buildRequest(nil, req)
if err != nil {
@@ -91,7 +76,7 @@ func (f *Fetcher) Resolve(req *base.Request) (*base.Resource, error) {
if err != nil {
return nil, err
}
res.TotalSize = parse
res.Length = parse
}
} else if base.HttpCodeOK == httpResp.StatusCode {
// 返回200响应码,不支持断点下载,通过Content-Length头获取文件大小,获取不到的话可能是chunked编码
@@ -101,13 +86,13 @@ func (f *Fetcher) Resolve(req *base.Request) (*base.Resource, error) {
if err != nil {
return nil, err
}
res.TotalSize = parse
res.Length = parse
}
} else {
return nil, NewRequestError(httpResp.StatusCode, httpResp.Status)
}
file := &base.FileInfo{
Size: res.TotalSize,
Size: res.Length,
}
contentDisposition := httpResp.Header.Get(base.HttpHeaderContentDisposition)
if contentDisposition != "" {
@@ -139,14 +124,14 @@ func (f *Fetcher) Create(res *base.Resource, opts *base.Options) error {
func (f *Fetcher) Start() (err error) {
// 创建文件
name := f.filename()
_, err = f.Ctl.Touch(name, f.res.TotalSize)
_, err = f.Ctl.Touch(name, f.res.Length)
if err != nil {
return err
}
f.status = base.DownloadStatusStart
if f.res.Range {
// 每个连接平均需要下载的分块大小
chunkSize := f.res.TotalSize / int64(f.opts.Connections)
chunkSize := f.res.Length / int64(f.opts.Connections)
f.chunks = make([]*Chunk, f.opts.Connections)
f.clients = make([]*http.Response, f.opts.Connections)
for i := 0; i < f.opts.Connections; i++ {
@@ -156,7 +141,7 @@ func (f *Fetcher) Start() (err error) {
)
if i == f.opts.Connections-1 {
// 最后一个分块需要保证把文件下载完
end = f.res.TotalSize - 1
end = f.res.Length - 1
} else {
end = begin + chunkSize - 1
}
@@ -340,7 +325,7 @@ func buildClient() *http.Client {
jar, _ := cookiejar.New(nil)
return &http.Client{
Jar: jar,
Timeout: time.Second * 10,
Timeout: time.Second * 60,
}
}
@@ -385,3 +370,40 @@ func buildRequest(ctx context.Context, req *base.Request) (httpReq *http.Request
httpReq.Header = headers
return httpReq, nil
}
type FetcherData struct {
Chunks []*Chunk
}
type FetcherBuilder struct {
}
var schemes = []string{"HTTP", "HTTPS"}
func (fb *FetcherBuilder) Schemes() []string {
return schemes
}
func (fb *FetcherBuilder) Build() fetcher.Fetcher {
return &Fetcher{
DefaultFetcher: new(fetcher.DefaultFetcher),
pauseCh: make(chan interface{}),
}
}
func (fb *FetcherBuilder) Store(f fetcher.Fetcher) interface{} {
_f := f.(*Fetcher)
return &FetcherData{
Chunks: _f.chunks,
}
}
func (fb *FetcherBuilder) Resume(res *base.Resource, opts *base.Options, data interface{}) fetcher.Fetcher {
fetcher := new(FetcherBuilder).Build().(*Fetcher)
fs := data.(*FetcherData)
fetcher.res = res
fetcher.opts = opts
fetcher.chunks = fs.Chunks
fetcher.status = base.DownloadStatusPause
return fetcher
}