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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user