Скачивание файла с указанием оставшегося времени
пишу небольшой скрипт, который будет скачивать большой файл, пока что получилось сделать по примеру:
package main
import (
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
"io"
"net/http"
"os"
)
func main() {
fileUrl := "https://golangcode.com/logo.svg"
err := DownloadFile("logo.svg", fileUrl)
if err != nil {
panic(err)
}
a := app.New()
w := a.NewWindow("Test")
w.SetContent(widget.NewLabel("Downloaded: " + fileUrl))
w.ShowAndRun()
}
func DownloadFile(filepath string, url string) error {
// Get the data
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
// Create the file
out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()
// Write the body to file
_, err = io.Copy(out, resp.Body)
return err
}
По коду понятно, что скачивается файл https://golangcode.com/logo.svg и сохраняется там, где запускается скрипт.
Так же есть a := app.New(), который, в будущем, будет придавать более красивый дизайн, чем обычная консоль.
Вот тут и возникает вопрос о времени скачивания, хотел бы сделать прогресс бар, в котором бы показывалось оставшееся время скачивания, вроде нашёл что-то вот такое: тык, где как раз и показываются проценты, но пока так и не разобрался, как это работает.
Ответы (1 шт):
Автор решения: Senior Pomidor
→ Ссылка
package main
import (
"fmt"
"io"
"net/http"
"os"
"strconv"
"time"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
var pb *widget.ProgressBar
func main() {
fmt.Println("Download Started")
a := app.New()
w := a.NewWindow("Test")
pb = widget.NewProgressBar()
w.SetContent(container.NewVBox(pb))
// запускаю в отдельной горутине, так как w.ShowAndRun() зависает до завершения процесса
go func() {
// картинка чуть тяжелее
fileUrl := "https://upload.wikimedia.org/wikipedia/commons/d/d6/Wp-w4-big.jpg"
err := DownloadFile("avatar.jpg", fileUrl)
if err != nil {
panic(err)
}
}()
w.ShowAndRun()
fmt.Println("Download Finished")
}
type WriteCounter struct {
Total uint64
ContentLength float64
}
func (wc *WriteCounter) Write(p []byte) (int, error) {
n := len(p)
wc.Total += uint64(n)
wc.PrintProgress()
return n, nil
}
func (wc WriteCounter) PrintProgress() {
// добавил слип чтобы увидеть прогресс бар. он тут нужен только для анимации. можете удалить.
time.Sleep(time.Millisecond * 100)
fmt.Printf("\rDownloading... %d complete", wc.Total)
// SetValue отображает проценты. поэтому мы считаем процент от всего объема данных
pb.SetValue(float64(wc.Total) / wc.ContentLength)
// перерисовываем
pb.Refresh()
}
func DownloadFile(filepath string, url string) error {
out, err := os.Create(filepath + ".tmp")
if err != nil {
return err
}
// Get the data
resp, err := http.Get(url)
if err != nil {
out.Close()
return err
}
defer resp.Body.Close()
contentLength, err := strconv.ParseFloat(resp.Header.Get("content-length"), 64)
if err != nil {
return err
}
counter := &WriteCounter{ContentLength: contentLength}
if _, err = io.Copy(out, io.TeeReader(resp.Body, counter)); err != nil {
out.Close()
return err
}
fmt.Print("\n")
out.Close()
if err = os.Rename(filepath+".tmp", filepath); err != nil {
return err
}
return nil
}