improve the built-in download function, enhance the logic robustness and reliability in adverse network environments
This commit is contained in:
parent
f373f1caa8
commit
4fb35845b0
@ -1,6 +1,7 @@
|
|||||||
package backend_golang
|
package backend_golang
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ func (a *App) DownloadFile(path string, url string) error {
|
|||||||
|
|
||||||
type DownloadStatus struct {
|
type DownloadStatus struct {
|
||||||
resp *grab.Response
|
resp *grab.Response
|
||||||
|
cancel context.CancelFunc
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
@ -29,7 +31,7 @@ type DownloadStatus struct {
|
|||||||
Done bool `json:"done"`
|
Done bool `json:"done"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var downloadList []DownloadStatus
|
var downloadList []*DownloadStatus
|
||||||
|
|
||||||
func existsInDownloadList(url string) bool {
|
func existsInDownloadList(url string) bool {
|
||||||
for _, ds := range downloadList {
|
for _, ds := range downloadList {
|
||||||
@ -41,49 +43,58 @@ func existsInDownloadList(url string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) PauseDownload(url string) {
|
func (a *App) PauseDownload(url string) {
|
||||||
for i, ds := range downloadList {
|
for _, ds := range downloadList {
|
||||||
if ds.Url == url {
|
if ds.Url == url {
|
||||||
if ds.resp != nil {
|
if ds.cancel != nil {
|
||||||
ds.resp.Cancel()
|
ds.cancel()
|
||||||
}
|
|
||||||
|
|
||||||
downloadList[i] = DownloadStatus{
|
|
||||||
resp: ds.resp,
|
|
||||||
Name: ds.Name,
|
|
||||||
Path: ds.Path,
|
|
||||||
Url: ds.Url,
|
|
||||||
Downloading: false,
|
|
||||||
}
|
}
|
||||||
|
ds.resp = nil
|
||||||
|
ds.Downloading = false
|
||||||
|
ds.Speed = 0
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) ContinueDownload(url string) {
|
func (a *App) ContinueDownload(url string) {
|
||||||
for i, ds := range downloadList {
|
for _, ds := range downloadList {
|
||||||
if ds.Url == url {
|
if ds.Url == url {
|
||||||
client := grab.NewClient()
|
if !ds.Downloading && ds.resp == nil && !ds.Done {
|
||||||
req, _ := grab.NewRequest(ds.Path, ds.Url)
|
ds.Downloading = true
|
||||||
resp := client.Do(req)
|
|
||||||
|
|
||||||
downloadList[i] = DownloadStatus{
|
req, err := grab.NewRequest(ds.Path, ds.Url)
|
||||||
resp: resp,
|
if err != nil {
|
||||||
Name: ds.Name,
|
ds.Downloading = false
|
||||||
Path: ds.Path,
|
break
|
||||||
Url: ds.Url,
|
}
|
||||||
Downloading: true,
|
// if PauseDownload() is called before the request finished, ds.Downloading will be false
|
||||||
|
// if the user keeps clicking pause and resume, it may result in multiple requests being successfully downloaded at the same time
|
||||||
|
// so we have to create a context and cancel it when PauseDownload() is called
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
ds.cancel = cancel
|
||||||
|
req = req.WithContext(ctx)
|
||||||
|
resp := grab.DefaultClient.Do(req)
|
||||||
|
|
||||||
|
if resp != nil && resp.HTTPResponse != nil &&
|
||||||
|
resp.HTTPResponse.StatusCode >= 200 && resp.HTTPResponse.StatusCode < 300 {
|
||||||
|
ds.resp = resp
|
||||||
|
} else {
|
||||||
|
ds.Downloading = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) AddToDownloadList(path string, url string) {
|
func (a *App) AddToDownloadList(path string, url string) {
|
||||||
if !existsInDownloadList(url) {
|
if !existsInDownloadList(url) {
|
||||||
downloadList = append(downloadList, DownloadStatus{
|
downloadList = append(downloadList, &DownloadStatus{
|
||||||
resp: nil,
|
resp: nil,
|
||||||
Name: filepath.Base(path),
|
Name: filepath.Base(path),
|
||||||
Path: a.exDir + path,
|
Path: a.exDir + path,
|
||||||
Url: url,
|
Url: url,
|
||||||
Downloading: true,
|
Downloading: false,
|
||||||
})
|
})
|
||||||
a.ContinueDownload(url)
|
a.ContinueDownload(url)
|
||||||
} else {
|
} else {
|
||||||
@ -96,32 +107,17 @@ func (a *App) downloadLoop() {
|
|||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
<-ticker.C
|
<-ticker.C
|
||||||
for i, ds := range downloadList {
|
for _, ds := range downloadList {
|
||||||
transferred := int64(0)
|
|
||||||
size := int64(0)
|
|
||||||
speed := float64(0)
|
|
||||||
progress := float64(0)
|
|
||||||
downloading := ds.Downloading
|
|
||||||
done := false
|
|
||||||
if ds.resp != nil {
|
if ds.resp != nil {
|
||||||
transferred = ds.resp.BytesComplete()
|
ds.Transferred = ds.resp.BytesComplete()
|
||||||
size = ds.resp.Size()
|
ds.Size = ds.resp.Size()
|
||||||
speed = ds.resp.BytesPerSecond()
|
ds.Speed = ds.resp.BytesPerSecond()
|
||||||
progress = 100 * ds.resp.Progress()
|
ds.Progress = 100 * ds.resp.Progress()
|
||||||
downloading = !ds.resp.IsComplete()
|
ds.Downloading = !ds.resp.IsComplete()
|
||||||
done = ds.resp.Progress() == 1
|
ds.Done = ds.resp.Progress() == 1
|
||||||
}
|
if !ds.Downloading {
|
||||||
downloadList[i] = DownloadStatus{
|
ds.resp = nil
|
||||||
resp: ds.resp,
|
}
|
||||||
Name: ds.Name,
|
|
||||||
Path: ds.Path,
|
|
||||||
Url: ds.Url,
|
|
||||||
Transferred: transferred,
|
|
||||||
Size: size,
|
|
||||||
Speed: speed,
|
|
||||||
Progress: progress,
|
|
||||||
Downloading: downloading,
|
|
||||||
Done: done,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
runtime.EventsEmit(a.ctx, "downloadList", downloadList)
|
runtime.EventsEmit(a.ctx, "downloadList", downloadList)
|
||||||
|
Loading…
Reference in New Issue
Block a user